Anexo
install.packages("faraway")
install.packages("leaps")
install.packages("MASS")
install.packages("PASWR")
install.packages("car")
install.packages("ggplot2")
install.packages("GGally")
install.packages("corrplot")
install.packages("scatterplot3d")
install.packages("lmtest")
install.packages("plotly")
install.packages("mixlm")
library(faraway)
library(leaps)
library(MASS)
library(PASWR)
library(car)
library(ggplot2)
library(GGally)
library(corrplot)
library(plotly)
library(scatterplot3d)
library(lmtest)
library(mixlm)
# 1) Introduccion
data(cheddar)
attach(cheddar)
# Variable Respuesta: taste
# Variables Predictoras: Acetic, H2S, Lactic
# Estudiamos el tipo de las variables que van a formar parte de los posibles modelos
sapply(cheddar, class) # todas las variables son numericas
head(cheddar)
# Comprobamos que no hay entradas vacias
any(is.na(cheddar))
# De haberlas habido, podriamos haber tomado las siguientes decisiones:
# - eliminar las observaciones con valores NA
# - eliminar variables si muchas de las entradas vacias aparecen en ella
# - emplear métodos para predecir que valores deberian apercer en dichas entradas
# Histogramas de todas las variables
ids <- names(cheddar)
layout(matrix(1:4, nrow = 1))
y_lab_string <- "Cantidad"
for (id in ids) {
hist(cheddar[, id], xlab = id, ylab = y_lab_string, main = paste("Histogram of ", id))
y_lab_string <- ""
}
# Graficas de las relaciones entre variables.
plot(cheddar)
# Graficas de dispersion entre la variable respuesta "taste" y las variables predictoras.
layout(matrix(1:3, nrow = 1))
plot(Acetic, taste,
main = "Relación entre Taste y Acetic",
xlab = "Acetic", ylab = "Taste",
pch = 19, frame = FALSE)
plot(H2S, taste,
main = "Relación entre Taste y H2S",
xlab = "H2S", ylab = "Taste",
pch = 19, frame = FALSE)
plot(Lactic, taste,
main = "Relación entre Taste y Lactic",
xlab = "Lactic", ylab = "Taste",
pch = 19, frame = FALSE)
layout(matrix(1:1, nrow = 1))
summary(cheddar)
# 2) Estudio y evaluacion del modelo completo
x <- model.matrix( ~ Acetic + H2S + Lactic, data = cheddar)
betahat <- solve(crossprod(x, x), crossprod(x, taste))
betahat <- c(betahat)
betahat
# Comprobamos el resultado con funciones ya implementadas
model.all <- lm(taste ~ ., data = cheddar)
summary(model.all)
model.all$coefficients
anova(model.all)
# Intervalos de confianza de las betas del modelo completo
confint(model.all)
# Observamos que 0 esta en el intervalo de confianza de beta_0 y beta_Acetic, planteamos dos tests
# con hipótesis nula beta_i = 0 y hipotesis alternativa beta_i != 0.
# Comenzamos con beta_Acetic pues el valor estimado es más cercano a 0 que el de beta_0
modnoAcetic <- lm(taste ~ H2S + Lactic, data=cheddar)
anova(modnoAcetic,model.all) # no solo el p-valor > 0.05 sino que de hecho p-valor ~ 1, aceptamos la hipotesis nula.
modnoInterceptor <- lm(taste ~ H2S + Lactic + 0, data=cheddar) # modelo reducido sin interceptor
anova(modnoInterceptor,model.all) # el p-valor es menor que 0.05, luego no es suficiente para rechazar la hipotesis nula
# Veamos los p-valores de las variables predictoras
summary(model.all)$coeff[,4]
# Observamso que el p-valor de Acetic es el mas elevado, este resultado junto con el contrate de hipotesis que hemos hecho
# podemos deducir que la variable Acetic no sera muy relevante para el estudio de los distintos modelos que estudiaremos.
# Correlaciones de las variables que intervienen en el modelo completo
cor(cheddar)
ggpairs(cheddar)
mat_cor <- cor(cheddar, method = "pearson")
corrplot(mat_cor, type = "upper", order = "hclust", tl.col = "black", tl.srt = 45)
# Por ultimo veamos si hay outliers en el modelo completo
Model.all<-fortify(model.all)
outlierTest(model.all) # no los hay
# Por el metodo de Bonferroni
alpha <- 0.05
BCV <- qt(1-alpha/(2*30),26) # el valor critico de Bonferroni t_{1-alpha/2n;n-p-1}, n=30,p=3
BCV
sum(abs(rstudent(model.all))>BCV) # el metodo no nos da ninguna observacion
sort(abs(rstandard(model.all)),decreasing = TRUE)[1:3] # estos valores estan relativamente lejanos de BCV
# Veamos si por influenceIndexPlot() hay alguna observacion que pueda ser relevante
influenceIndexPlot(model.all) # en la tercera grafica se ve que la observacion 15 tiene un comportamiento anormal
# Comprobemos si los supuestos de los modelos de regresion lineal mejoran al retirar esta observacion
# de nuestro dataset. De ser asi, aceptamos que pueda ser una observacion que pejudique a nuestro modelo.
model.all_15<- lm(taste ~ ., data = cheddar[-15,])
# Homocedasticidad
ncvTest(model.all)
ncvTest(model.all_15) # empeora
# Normalidad
shapiro.test(resid(model.all))
shapiro.test(resid(model.all_15))# mejora
# Autocorrelacion
durbinWatsonTest(model.all)
durbinWatsonTest(model.all_15)# mejora
# Linealidad
resettest(model.all, power=2:3, type="regressor", data=cheddar)
resettest(model.all_15, power=2:3, type="regressor", data=cheddar)# empeora
# En el computo global no parece que los p-valores de estos tests den a entender una mejoria general del modelo.
# Si bien es cierto, tampoco los empeora y dependiendo del criterio a seguir podriamos decidir si es relevante o no.
# Nosotros hemos decidido no considerar la observacion 15 como tal.
# 3) Seleccion del mejor modelo. Metodos por pasos y por criterios
# Separacion del dataset en conjuntos de entrenamiento y test (70-30%)
# Hemos considerado varias semillas para abarcar más modelos. Además, hemos intentado evitar
# en la medida de lo poible que se repitan muchos elementos en los distintos conjuntos de test seleccionados.
set.seed(1)
train.1 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.1 <- (!train.1)
sum(test.1)
model.all1 <- lm(taste ~ ., data = cheddar[train.1,])
set.seed(1100)
train.2 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.2 <- (!train.2)
sum(test.2)
sum(test.1==TRUE & test.2==TRUE)#solo 1 preseguimos
model.all2 <- lm(taste ~ ., data = cheddar[train.2,])
set.seed(5)
train.3 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.3 <- (!train.3)
sum(test.3)
sum(test.1==TRUE & test.3==TRUE)
sum(test.2==TRUE & test.3==TRUE)
model.all3 <- lm(taste ~ ., data = cheddar[train.3,])
# i) BACKWARD (alpha=0.05)
drop1(model.all1, test = "F")
# quitamos Acetic del modelo por ser la de mayor p-valor
model.updateB1 <- update(model.all1, . ~ . - Acetic)
drop1(model.updateB1, test = "F")
# quitamos H2S del modelo por ser la de mayor p-valor
model.updateB2 <- update(model.updateB1, . ~ . - H2S)
drop1(model.updateB2, test = "F")
# termina el proceso pues el p-valor de Lactic no llega a alpha
model.1 <- lm(taste ~ Lactic, data = cheddar[train.1,])
summary(model.1)
# Para evitar repetir este proceso usamos el package mixlm con el que obtenemos los mismos resultados.
model.1 <- mixlm::backward(model.all1, alpha=0.05)
summary(model.1) # LACTIC
model.2 <- mixlm::backward(model.all2, alpha=0.05)
summary(model.2) # H2S + LACTIC
model.3 <- mixlm::backward(model.all3, alpha=0.05)
summary(model.3) # H2S + LACTIC
# ii) FORWARD (alpha=0.05)
SCOPE <- (~ . + Acetic + H2S + Lactic)
model.inicial <- lm(taste ~ 1, data = cheddar[train.1,]) # solo con termino independiente
add1(model.inicial, scope = SCOPE, test = "F")
# Añadimos Lactic por ser la variable predictora con menor p-valor
model.updateF1 <- update(model.inicial, . ~ . + Lactic)
add1(model.updateF1, scope = SCOPE, test = "F")
# No añadimos ninguna variable pues todos los p-valores superan la barrera de alpha
model.1a <- lm(taste ~ Lactic, data = cheddar[train.1,])
summary(model.1a)
# Al igual que en BACKWARD usamos el paquete mixlm para automatizar el proceso de FORWARD.
model.1a <- mixlm::forward(model.all1, alpha=0.05)
summary(model.1a) # LACTIC
model.2a <- mixlm::forward(model.all2, alpha=0.05)
summary(model.2a) # H2S + LACTIC
model.3a <- mixlm::forward(model.all3, alpha=0.05)
summary(model.3a) # H2S + LACTIC
# Nótese que los modelos obtenidos por BACKWARD y FORWARD coinciden para cada conjunto train.
# iii) CRITERIOS
# R2 ajustado
models1 <- regsubsets(taste ~ ., data = cheddar[train.1,])
models2 <- regsubsets(taste ~ ., data = cheddar[train.2,])
models3 <- regsubsets(taste ~ ., data = cheddar[train.3,])
summary(models1)
summary(models2)
summary(models3)
MR2adj1 <- summary(models1)$adjr2
MR2adj2 <- summary(models2)$adjr2
MR2adj3 <- summary(models3)$adjr2
summary(models1)$which[which.max(MR2adj1), ]
summary(models2)$which[which.max(MR2adj2), ]
summary(models3)$which[which.max(MR2adj3), ]
# Cp de Mallows
MCp1 <- summary(models1)$cp
MCp2 <- summary(models2)$cp
MCp3 <- summary(models3)$cp
summary(models1)$which[which.min(MCp1), ]
summary(models2)$which[which.min(MCp2), ]
summary(models3)$which[which.min(MCp3), ]
# Criterio de Informacion de Bayes (BIC)
MBIC1 <- summary(models1)$bic
MBIC2 <- summary(models2)$bic
MBIC3 <- summary(models3)$bic
summary(models1)$which[which.min(MBIC1), ]
summary(models2)$which[which.min(MBIC2), ]
summary(models3)$which[which.min(MBIC3), ]
# Criterio de Informacion de Akaike (AIC)
stepAIC(model.all1, scope = SCOPE, k = 2)
stepAIC(model.all2, scope = SCOPE, k = 2)
stepAIC(model.all3, scope = SCOPE, k = 2)
# Para el conjunto train.1 aparecen modelos con Lactic y H2S + Lactic como variables predictoras,
# mientras que para los conjuntos train.2 y train.3 unicamente aparece el modelo taste ~ H2S + Lactic.
model.1crit <- lm(taste ~ H2S + Lactic, data=cheddar[train.1,])
# Esto nos puede llevar a pensar que el modelo final vaya a ser el que utiliza H2S y Lactic.
model.1
model.1crit
model.2
model.3
anova(model.1,model.all1)
anova(model.1crit,model.all1)
anova(model.2,model.all2)
anova(model.3,model.all3)
# De esta forma vemos que los modelos creados son mejores que los completos.
# 4) Diagnostico. Comprobaciones de hipotesis, outliers y observaciones influyentes
# Comprobacion de hipotesis de los modelos
# Linealidad
resettest(model.1, power=2:3, type="regressor", data=cheddar[train.1,])
resettest(model.1crit, power=2:3, type="regressor", data=cheddar[train.1,])
resettest(model.2, power=2:3, type="regressor", data=cheddar[train.2,])
resettest(model.3, power=2:3, type="regressor", data=cheddar[train.3,])
# p-valores > 0.05 luego aceptamos hipótesis de linealidad en todos los casos
plot(cheddar$H2S, cheddar$taste,
main = "Relacion entre Taste y H2S",
xlab = "H2S", ylab = "Taste",
pch = 19, frame = FALSE)
plot(cheddar$Lactic, cheddar$taste,
main = "Relacion entre Taste y Lactic",
xlab = "Lactic", ylab = "Taste",
pch = 19, frame = FALSE)
# Normalidad y Autocorrelacion
shapiro.test(resid(model.1)) # p-valor > 0.05 no se rechaza la hipótesis nula, i.e. la normalidad
qqnorm(resid(model.1))
qqline(resid(model.1))
shapiro.test(resid(model.1crit))#bien
qqnorm(resid(model.1crit))
qqline(resid(model.1crit))
shapiro.test(resid(model.2))#bien
qqnorm(resid(model.2))
qqline(resid(model.2))
shapiro.test(resid(model.3))#bien
qqnorm(resid(model.3))
qqline(resid(model.3))
# Observamos que las colas no siguen el mismo patrón que el resto de datos, lo que podrÃa indicar que
# el modelo no sigue una distribución normal. Sin embargo, al no afectar a un gran porcentaje de los datos y
# teniendo en cuenta el resultado previo obtenido por el Test de Shapiro-Wilk no rechazamos la hipótesis de normalidad.
# Media de errores nula
t.test(resid(model.1), mu = 0, alternative = "two.sided")
t.test(resid(model.1crit), mu = 0, alternative = "two.sided")
t.test(resid(model.2), mu = 0, alternative = "two.sided")
t.test(resid(model.3), mu = 0, alternative = "two.sided")
# p-valores ~ 1 > 0.05 luego aceptamos la hipotesis nula en todos los casos
# Autocorrelacion
durbinWatsonTest(model.1)
durbinWatsonTest(model.1crit)
durbinWatsonTest(model.2)
durbinWatsonTest(model.3)
# p-valores > 0.05 luego rechazamos que haya autocorrelacion
# Homocedasticidad
fmodel1 <- fortify(model.1)
fmodel1crit <- fortify(model.1crit)
fmodel2 <- fortify(model.2)
fmodel3 <- fortify(model.3)
X1 <- fmodel1$.fitted
Y1 <- fmodel1$.stdresid
X1crit <- fmodel1crit$.fitted
Y1crit <- fmodel1crit$.stdresid
X2 <- fmodel2$.fitted
Y2 <- fmodel2$.stdresid
X3 <- fmodel3$.fitted
Y3 <- fmodel3$.stdresid
plot(X1, Y1, ylab = "Residuos estandarizados", xlab = "valores ajustados")
plot(X1crit, Y1crit, ylab = "Residuos estandarizados", xlab = "valores ajustados")
plot(X2, Y2, ylab = "Residuos estandarizados", xlab = "valores ajustados")#casi casi hay patron
plot(X3, Y3, ylab = "Residuos estandarizados", xlab = "valores ajustados")
# Los residuos se distribuyen de forma homogénea a lo largo de una banda horizontal, luego se verifica la hipótesis nula
ncvTest(model.1)
ncvTest(model.1crit)
ncvTest(model.2)
ncvTest(model.3)
# p-valores > 0.05, luego no hay evidencia para rechazar que la varianza sea constante
# Outliers
alpha <- 0.05
n1 <- nrow(cheddar[train.1,])
p1 <- nrow(summary(model.1)$coef)
n1crit <- nrow(cheddar[train.1,])
p1crit <- nrow(summary(model.1crit)$coef)
n2 <- nrow(cheddar[train.2,])
p2 <- nrow(summary(model.2)$coef)
n3 <- nrow(cheddar[train.3,])
p3 <- nrow(summary(model.3)$coef)
# El valor critico de Bonferroni t_{1-alpha/2n;n-p-1}
BCV1 <- qt(1 - alpha / (2 * n1), n1-p1-1)
BCV1crit <- qt(1 - alpha / (2 * n1crit), n1crit-p1crit-1)
BCV2 <- qt(1 - alpha / (2 * n2), n2-p2-1)
BCV3 <- qt(1 - alpha / (2 * n3), n3-p3-1)
sum(abs(rstudent(model.1)) > BCV1)
sum(abs(rstudent(model.1crit)) > BCV1crit)
sum(abs(rstudent(model.2)) > BCV2)
sum(abs(rstudent(model.3)) > BCV3)
outlierTest(model.1)#NA?
outlierTest(model.1crit) #NA?
outlierTest(model.2)
outlierTest(model.3)
# No hay outliers en ninguno de los dos modelos planteados
# Observaciones Influyentes
# Criterio 1: valores leverage (hii) mayores que 2p/n
X1 <- model.matrix(~ H2S+Lactic, data = cheddar[train.1,])
X1crit <- model.matrix(~ H2S+Lactic, data = cheddar[train.1,])
X2 <- model.matrix(~ H2S+Lactic, data = cheddar[train.2,])
X3 <- model.matrix(~ Lactic, data = cheddar[train.3,])
H1 <- X1 %*% solve(t(X1) %*% X1) %*% t(X1)
H1crit <- X1crit %*% solve(t(X1crit) %*% X1crit) %*% t(X1crit)
H2 <- X2 %*% solve(t(X2) %*% X2) %*% t(X2)
H3 <- X3 %*% solve(t(X3) %*% X3) %*% t(X3)
hii1 <- diag(H1)
hii1crit <- diag(H1crit)
hii2 <- diag(H2)
hii3 <- diag(H3)
hCV1 <- 2 * p1 / n1
hCV1crit <- 2 * p1crit / n1crit
hCV2 <- 2 * p2 / n2
hCV3 <- 2 * p3 / n3
sum(hii1 > hCV1)
which(hii1>hCV1)#1 5 16 23 24 26
sum(hii1crit > hCV1crit)
which(hii1crit>hCV1crit)
sum(hii2 > hCV2)
which(hii2>hCV2)
sum(hii3 > hCV3)
# Criterio 2: valores |DFFITS| son mayores que 2*sqrt(p/n)
dffitsCV1 <- 2 * sqrt(p1 / n1)
dffitsCV1crit <- 2 * sqrt(p1crit / n1crit)
dffitsCV2 <- 2 * sqrt(p2 / n2)
dffitsCV3 <- 2 * sqrt(p3 / n3)
dffitsmodel1 <- dffits(model.1)
dffitsmodel1crit <- dffits(model.1crit)
dffitsmodel2 <- dffits(model.2)
dffitsmodel3 <- dffits(model.3)
sum(dffitsmodel1 > dffitsCV1)
which(dffitsmodel1 > dffitsCV1)#1 12 24
sum(dffitsmodel1crit > dffitsCV1crit)
which(dffitsmodel1crit > dffitsCV1crit)#1, 12
sum(dffitsmodel2 > dffitsCV2)
sum(dffitsmodel3 > dffitsCV3)
# Criterio 3: valores |DFBETAS| mayores que 2/sqrt(n)
dfbetaCV1 <- 2 / sqrt(n1)
dfbetaCV1crit <- 2 / sqrt(n1crit)
dfbetaCV2 <- 2 / sqrt(n2)
dfbetaCV3 <- 2 / sqrt(n3)
dfbetamodel1 <- dfbeta(model.1)
dfbetamodel1crit <- dfbeta(model.1crit)
dfbetamodel2 <- dfbeta(model.2)
dfbetamodel3 <- dfbeta(model.3)
sum(dfbetamodel1[, 1] > dfbetaCV1)
sum(dfbetamodel1[, 2] > dfbetaCV1)
which(dfbetamodel1[, 1] > dfbetaCV1)
which(dfbetamodel1[, 2] > dfbetaCV1)
sum(dfbetamodel1crit[, 1] > dfbetaCV1crit)
sum(dfbetamodel1crit[, 2] > dfbetaCV1crit)
sum(dfbetamodel1crit[, 3] > dfbetaCV1crit)
which(dfbetamodel1crit[, 1] > dfbetaCV1crit)
which(dfbetamodel1crit[, 3] > dfbetaCV1crit)
sum(dfbetamodel2[, 1] > dfbetaCV2)
sum(dfbetamodel2[, 2] > dfbetaCV2)
sum(dfbetamodel2[, 3] > dfbetaCV2)
which(dfbetamodel2[, 1] > dfbetaCV2)
which(dfbetamodel2[, 3] > dfbetaCV2)
sum(dfbetamodel3[, 1] > dfbetaCV3)
sum(dfbetamodel3[, 2] > dfbetaCV3)
sum(dfbetamodel3[, 3] > dfbetaCV3)
which(dfbetamodel3[, 1] > dfbetaCV3)
which(dfbetamodel3[, 3] > dfbetaCV3)
# Dado que nuestro datset es pequeño, no tendremso en cuenta este metodo por dar demasiadas observaciones.
# Grafica con las distancias de Cook
influencePlot(model.1)
pos_influyentes_1 <- c(1,12,24)
influencePlot(model.1crit)
pos_influyentes_1crit <- c(1,8,12,23)
influencePlot(model.2)
pos_influyentes_2 <- c(1,6,7,8,15)
influencePlot(model.3)
pos_influyentes_3 <- c(1,7,15,19,24)
# Colinealidad
vif(model.1) # tiene sentido pues en model.1 solo hay una variable predictora
vif(model.1crit)
vif(model.2)
vif(model.3) # como los valores de VIF no son grando, no indican colinealidad grave
# Vamos a tomar como posibles influyentes las que aparecen por varios metodos en cada modelo
# En el 1: 1 12
pos_1 <- c(TRUE,rep(FALSE,10),TRUE,rep(FALSE,18))
train.1inf <- train.1&!pos_1
model.1inf <- lm(taste ~ Lactic, data = cheddar[train.1inf,])
ncvTest(model.1)
ncvTest(model.1inf) # empeora pero sigue cumpliendo la hipotesis
shapiro.test(resid(model.1))
shapiro.test(resid(model.1inf)) # mejora poco
durbinWatsonTest(model.1)
durbinWatsonTest(model.1inf) # mejora
resettest(model.1, power=2:3, type="regressor", data=cheddar[train.1inf,])
resettest(model.1inf, power=2:3, type="regressor", data=cheddar[train.1inf,]) # mejora bastante
# Redefinimos el modelo eliminando las observaciones influyentes de pos_1.
train.1aux<-train.1
train.1 <- train.1inf
model.1 <- model.1inf
# En el 1crit: 1 12 23
pos_1crit <- c(TRUE,rep(FALSE,10),TRUE,rep(FALSE,10),TRUE,rep(FALSE,7))
train.1critinf <- train.1&!pos_1crit
model.1critinf <- lm(taste ~H2S+Lactic , data = cheddar[train.1critinf,])
ncvTest(model.1crit)
ncvTest(model.1critinf) # empeora
shapiro.test(resid(model.1crit))
shapiro.test(resid(model.1critinf)) # mejora
durbinWatsonTest(model.1crit)
durbinWatsonTest(model.1critinf) # mejora bastante
resettest(model.1crit, power=2:3, type="regressor", data=cheddar[train.1,])
resettest(model.1critinf, power=2:3, type="regressor", data=cheddar[train.1critinf,]) # empeora dentro de aceptable
# Redefinimos el modelo eliminando las observaciones influyentes de pos_1crit.
train.1crit <- train.1critinf
model.1crit <- model.1critinf
# En el 2: 6
pos_2 <- c(rep(FALSE,5),TRUE,rep(FALSE,24))
train.2inf <- train.2&!pos_2
model.2inf <- lm(taste ~ H2S+Lactic, data = cheddar[train.2inf,])
ncvTest(model.2)
ncvTest(model.2inf) # mejora poco
shapiro.test(resid(model.2))
shapiro.test(resid(model.2inf)) # aproximadamente lo mismo
durbinWatsonTest(model.2)
durbinWatsonTest(model.2inf) # mejora
resettest(model.2, power=2:3, type="regressor", data=cheddar[train.2inf,])
resettest(model.2inf, power=2:3, type="regressor", data=cheddar[train.2inf,]) # aproximadamente lo mismo
# Redefinimos el modelo eliminando las observaciones influyentes de pos_2.
train.2 <- train.2inf
model.2 <- model.2inf
# En el modelo 3 no hacemos comprobaciones nada ya que no se repiten observaciones por distintos metodos.
# 5) Errores de Test. Comparacion de Modelos
# Vamos a considerar otras dos semillas para evaluar los modelos y elegir el mejor.
# Las tomamos de forma que no coincidan en la medida de lo posible los tests de las distintas particiones.
# Dividimos el conjunto total para las dos semillas nuevas.
set.seed((2234))
train.4 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.4 <- (!train.4)
sum(test.4)
sum(test.1==TRUE & test.4==TRUE)
sum(test.2==TRUE & test.4==TRUE)
sum(test.3==TRUE & test.4==TRUE)
set.seed((131))
train.5 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.5 <- (!train.5)
sum(test.5)
sum(test.1==TRUE & test.5==TRUE)
sum(test.2==TRUE & test.5==TRUE)
sum(test.3==TRUE & test.5==TRUE)
sum(test.4==TRUE & test.5==TRUE)
train.1h <- train.1crit
train.2h <- train.2
train.3h <- train.3
train.4h <- train.4
train.5h <- train.5
# Recalculamos train.2 porque fue modificado
set.seed(1100)
train.2 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
# Veamso si podemos eliminar posibles influyentes en los modelos restantes
mh1 <- lm(taste ~ H2S + Lactic, data = cheddar[train.1h,]) # comprobados supuestos
mh2 <- lm(taste ~ H2S + Lactic, data = cheddar[train.2h,]) # comprobados supuestos
mh3 <- lm(taste ~ H2S + Lactic, data = cheddar[train.3h,]) # comprobados supuestos
mh4 <- lm(taste ~ H2S + Lactic, data = cheddar[train.4h,])
mh5 <- lm(taste ~ H2S + Lactic, data = cheddar[train.5h,])
m1 <- lm(taste ~ Lactic, data = cheddar[train.1,]) # comprobados supuestos
m2 <- lm(taste ~ Lactic, data = cheddar[train.2,])
m3 <- lm(taste ~ Lactic, data = cheddar[train.3,])
m4 <- lm(taste ~ Lactic, data = cheddar[train.4,])
m5 <- lm(taste ~ Lactic, data = cheddar[train.5,])
# Al igual que hicimos en 4 comprobamos si retirando outliers y observaciones influyentes mejoran las hipotesis.
# Unicamente consideraremos observaciones obtenidas tanto por outlierTest() como por influencePlot().
# mh4
outlierTest(mh4)
influencePlot(mh4) # 6,12,15,24
pos4h <- c(rep(FALSE,5),TRUE,rep(FALSE,5),TRUE,rep(FALSE,2),TRUE,rep(FALSE,8),TRUE,rep(FALSE,6))
train.4inf <- train.4h&!pos4h
mh4inf <- lm(taste ~ H2S+Lactic, data = cheddar[train.4inf,])
ncvTest(mh4)
ncvTest(mh4inf) # mejora MUCHO
shapiro.test(resid(mh4))
shapiro.test(resid(mh4inf)) # mejora
durbinWatsonTest(mh4)
durbinWatsonTest(mh4inf) # mejora
resettest(mh4, power=2:3, type="regressor", data=cheddar[train.4inf,])
resettest(mh4inf, power=2:3, type="regressor", data=cheddar[train.4inf,]) # empeora pero es aceptable
# Redefinimos eliminando pos4h por ser tanta la mejora en homocedasticidad que compensa la linealidad
train.4h <- train.4inf
mh4 <- mh4inf
# mh5
outlierTest(mh5)
influencePlot(mh5) # 6,7,8,12,15
pos5h <- c(rep(FALSE,5),TRUE,TRUE,TRUE,rep(FALSE,3),TRUE,rep(FALSE,2),TRUE,rep(FALSE,15))
train.5inf <- train.5h&!pos5h
mh5inf <- lm(taste ~ H2S+Lactic, data = cheddar[train.5inf,])
ncvTest(mh5)
ncvTest(mh5inf) # mejora
shapiro.test(resid(mh5))
shapiro.test(resid(mh5inf)) # empeora
durbinWatsonTest(mh5)
durbinWatsonTest(mh5inf) # a veces no se cumple la hipotesis nula de no autocorrelacion
resettest(mh5, power=2:3, type="regressor", data=cheddar[train.5inf,])
resettest(mh5inf, power=2:3, type="regressor", data=cheddar[train.5inf,]) # empeora
# Decidimos no actualizar el modelo pues no siempre se rechaza la correlacion y empeoran otros p-valores.
# m2
outlierTest(m2)
influencePlot(m2) # 1,12,15,18,24
pos2 <- c(TRUE,rep(FALSE,10),TRUE,rep(FALSE,2),TRUE,rep(FALSE,2),TRUE,rep(FALSE,5),TRUE,rep(FALSE,6))
train.2inf <- train.2&!pos2
m2inf <- lm(taste ~ Lactic, data = cheddar[train.2inf,])
ncvTest(m2)
ncvTest(m2inf) # empeora ligeramente
shapiro.test(resid(m2))
shapiro.test(resid(m2inf)) # empeora ligeramente
durbinWatsonTest(m2)
durbinWatsonTest(m2inf) # empeora bastante
resettest(m2, power=2:3, type="regressor", data=cheddar[train.2inf,])
resettest(m2inf, power=2:3, type="regressor", data=cheddar[train.2inf,]) # mejora
# Decicimos no redefinirlo, ya que empeora en muchas y mejora bastante en una
# m3
outlierTest(m3)
influencePlot(m3) # 1,15,19,24
pos3 <- c(TRUE,rep(FALSE,13),TRUE,rep(FALSE,3),TRUE,rep(FALSE,4),TRUE,rep(FALSE,6))
train.3inf <- train.3&!pos3
m3inf <- lm(taste ~ Lactic, data = cheddar[train.3inf,])
ncvTest(m3)
ncvTest(m3inf) # mejora poco
shapiro.test(resid(m3))
shapiro.test(resid(m3inf)) # mejora
durbinWatsonTest(m3)
durbinWatsonTest(m3inf) # empeora
resettest(m3, power=2:3, type="regressor", data=cheddar[train.3inf,])
resettest(m3inf, power=2:3, type="regressor", data=cheddar[train.3inf,]) # empeora casi lo pierde
# Decidimos no redefinirlo por estar al borde en un criterio y no mejorar mucho en otros
# m4
outlierTest(m4)
influencePlot(m4) # 6,12,15,20,24
pos4 <- c(rep(FALSE,5),TRUE,rep(FALSE,5),TRUE,rep(FALSE,2),TRUE,rep(FALSE,4),TRUE,rep(FALSE,3),TRUE,rep(FALSE,6))
train.4inf <- train.4&!pos4
m4inf <- lm(taste ~ Lactic, data = cheddar[train.4inf,])
ncvTest(m4)
ncvTest(m4inf) # empeora bastante
shapiro.test(resid(m4))
shapiro.test(resid(m4inf)) # empeora
durbinWatsonTest(m4)
durbinWatsonTest(m4inf)# empeora bastante
resettest(m4, power=2:3, type="regressor", data=cheddar[train.4inf,])
resettest(m4inf, power=2:3, type="regressor", data=cheddar[train.4inf,]) # mejora algo
# Decidimos no cambiarlo porque empeora en casi todo, y de por si tenia buenos p-values
# m5
outlierTest(m5)
influencePlot(m5) # 1,8,12,15,18,24
pos5 <- c(TRUE,rep(FALSE,6),TRUE,rep(FALSE,3),TRUE,rep(FALSE,2),TRUE,rep(FALSE,2),TRUE,rep(FALSE,5),TRUE,rep(FALSE,6))
train.5inf <- train.5&!pos5
m5inf <- lm(taste ~ Lactic, data = cheddar[train.5inf,])
ncvTest(m5)
ncvTest(m5inf) # empeora bastante
shapiro.test(resid(m5))
shapiro.test(resid(m5inf)) # mejora
durbinWatsonTest(m5)
durbinWatsonTest(m5inf) # no se verifica la hipotesis nula de no autocorrelacion
resettest(m5, power=2:3, type="regressor", data=cheddar[train.5inf,])
resettest(m5inf, power=2:3, type="regressor", data=cheddar[train.5inf,]) # empeora
# Decidimos no cambiarlo por perderse la correlación
# Notese que en los originales siempre se cumplian las hipotesis, aunque no era necesario para el proceso
lista_test <- list(test.1,test.2,test.3,test.4,test.5)
lista_trainh <- list(train.1h,train.2h,train.3h,train.4h,train.5h)
lista_train <- list(train.1,train.2,train.3,train.4,train.5)
modelos_hip <- c("S1 taste ~ H2s + Lactic",
"S1 taste ~ Lactic",
"S2 taste ~ H2s + Lactic",
"S2 taste ~ Lactic",
"S3 taste ~ H2s + Lactic",
"S3 taste ~ Lactic",
"S4 taste ~ H2s + Lactic",
"S4 taste ~ Lactic",
"S5 taste ~ H2s + Lactic",
"S5 taste ~ Lactic",
"Nivel de significacion")
hip_RL <- c("Distribución_normal",
"Media_0",
"Varianza_no_constante",
"No_Autocorrelación")
placeholder <- vector(mode = "logical",length = 11)
df_hipRL <- data.frame("0" = placeholder,
"1" = placeholder,
"2" = placeholder,
"3" = placeholder,
row.names = modelos_hip)
colnames(df_hipRL) <- hip_RL
r <- 1
for (dtrain in lista_trainh){
model.HL.lm <- lm(taste ~ H2S + Lactic,
data = cheddar[dtrain,])
residuos <- resid(model.HL.lm)
new_row <- c()
shap <- round(shapiro.test(residuos)$p.value,4)
t <- t.test(residuos, mu = 0, alternative = "two.sided")$p.value
v <- round(ncvTest(model.HL.lm)$p,4)
dw <- round(durbinWatsonTest(model.HL.lm)$p,4)
new_row = c(shap,t,v,dw)
df_hipRL[r,] <- new_row
r = r + 2
}
r <- 2
for (dtrain in lista_train){
model.L.lm <- lm(taste ~Lactic,
data = cheddar[dtrain,])
residuos <- resid(model.L.lm)
new_row <- c()
shap <- round(shapiro.test(residuos)$p.value,4)
t <- t.test(residuos, mu = 0, alternative = "two.sided")$p.value
v <- round(ncvTest(model.L.lm)$p,4)
dw <- round(durbinWatsonTest(model.L.lm)$p,4)
new_row = c(shap,t,v,dw)
df_hipRL[r,] <- new_row
r = r + 2
}
df_hipRL[11,] <- c(rep(0.05,4))
df_hipRL # Todos los modelos cumplen las hipótesis
err1 <- 0
for (i in 5){
dtrain <- lista_trainh[[i]]
dtest <- lista_test[[i]]
dmod <- lm(taste ~ H2S + Lactic, data = cheddar[dtrain,])
Y <- cheddar[dtest,]$taste
Yhat <- predict(obj = dmod, newdata = cheddar[dtest,])
err1 <- err1 + mean((Y - Yhat)^2)
}
err1 <- err1/5
err1 # H2S + LACTIC tiene error medio 11.63
err2<-0
for (i in 5){
dtrain <- lista_train[[i]]
dtest <- lista_test[[i]]
dmod <- lm(taste ~ Lactic, data = cheddar[dtrain,])
Y <- cheddar[dtest,]$taste
Yhat <- predict(obj = dmod, newdata = cheddar[dtest,])
err2 <- err2 + mean((Y - Yhat)^2)
}
err2 <- err2/5
err2 # LACTIC tiene error medio 19.4
err1 < err2 # Concluimos que el modelo taste ~ H2S + Lactic es mejor que taste ~ Lactic.
# 6) Conclusion
model.y <- lm(taste ~ H2S + Lactic,data=cheddar) # tomamos el mejor modelo de los obtenidos en 4
summary(model.y)
plot(model.y)
# Veamos los posibles outliers
outlierTest(model.y)
influencePlot(model.y)
# Estudio de hipótesis supuestas
shapiro.test(resid(model.y)) # normalidad de residuos
t.test(resid(model.y), mu = 0, alternative = "two.sided") # media cero de los residuos
ncvTest(model.y) # varianza constante de los residuos
durbinWatsonTest(model.y) # no autocorrelacion
resettest(model.y ,power=2:3, type="regressor", data=cheddar) # linealidad
# Efectivamente, cumple todas las hipótesis
summary(model.y) # en el summary observamos los valores de betahat, sus p-valores y sigma
coeff <- summary(model.y)$coeff[,1]
coeff
# Calculo de intervalo de confianza de beta1(H2S) y beta2(Lactic)
# Metodo Bonferroni
alpha <- 0.10
summary(model.y)$coef
b <- summary(model.y)$coef[2:3, 1]
s.b <- summary(model.y)$coef[2:3, 2]
g <- 3
n <- nrow(cheddar)
p <- ncol(summary(model.y)$coef)
t_teo <- qt(1 - alpha / (2 * g), n - p)
BomSimCI <- matrix(c(b - t_teo * s.b, b + t_teo * s.b), ncol = 2)
conf <- c("5%", "95%")
bnam <- c("H2S", "Lactic")
dimnames(BomSimCI) <- list(bnam, conf)
BomSimCI
# Intervalo de confianza simultaneo por el metodo de Scheffe
Q <- p - 1
f_teo <- qf(0.9, Q, n - p)#0.9 no seria 0.95?
SchSimCI <- matrix(c(b - sqrt(Q * f_teo) * s.b, b + sqrt(Q * f_teo) * s.b), ncol = 2)
conf <- c("5%", "95%")
bnam <- c("H2S", "Lactic")
dimnames(SchSimCI) <- list(bnam, conf)
SchSimCI
# La ecuación de nuestro modelo final es y = (-27.6) + 3.95*x_H + 19.9*x_L,
# donde x_H y x_L denotan los valores observados de H2S y Lactic.
rse <- sqrt(deviance(model.y)/df.residual(model.y))
rse # varianza de los residuos
pval <- summary(model.y)$coeff[,4]
pval # vector con los p-valores
# Calculo de su R^2
anova(model.y)
SSE <- anova(model.y)[3,2]
SST <- anova(model.y)[1,2]+anova(model.y)[2,2]+anova(model.y)[3,2]
rsqr <- 1 - SSE/SST
rsqr
summary(model.y)$r.squared# es la misma
# Calculo de su R^2 ajustada
MSE <- SSE/anova(model.y)[3,1]
MST <- SST/(anova(model.y)[1,1]+anova(model.y)[2,1]+anova(model.y)[3,1])
Radj <-1-MSE/MST
Radj # se comprueba en la tabla summary que el valor es correcto
# Observamos como se distribuye la variable taste en función de H2S y Lactic
plot_ly(x=H2S, y=Lactic, z=taste, type="scatter3d", mode="marker", color=taste) %>%
layout(scene = list(xaxis = list(title = 'H2S (%)'),
yaxis = list(title = 'Lactic (%)'),
zaxis = list(title = 'Taste (0-100)')))
# Vemos el plano de regresion del modelo propuesto.
# En rojo se marcan las observaciones que peor se ajustan al modelo.
planereg <- scatterplot3d(x=H2S, y=Lactic, z=taste, pch=16, cex.lab=1,
highlight.3d=TRUE, type="h", xlab='H2S (%)',
ylab='Lactic (%)', zlab='Taste (0-100)')
planereg$plane3d(model.y, lty.box="solid", col='mediumblue')
LS0tDQp0aXRsZTogJ1JlZ3Jlc2nDs246IE1vZGVsb3MgRXN0YWTDrXN0aWNvcycNCmF1dGhvcjoNCi0gbmFtZTogRGFuaWVsIEzDs3BleiBNb250ZXJvDQotIG5hbWU6IFJvZHJpZ28gZGUgbGEgTnVleiBNb3JhbGVkYQ0KLSBuYW1lOiBKb3PDqSBHYXJjw61hIFJlYm9sbG8NCi0gbmFtZTogRGF2aWQgUGFycm8gUGxhemENCm91dHB1dDoNCiAgcGRmX2RvY3VtZW50Og0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnMycNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KYWx3YXlzX2FsbG93X2h0bWw6IHllcw0KYWJzdHJhY3Q6IHwNCiAgSGVtb3MgYW5hbGl6YWRvIGNvbiBsYXMgaGVycmFtaWVudGFzIHByb3BvcmNpb25hZGFzIGVuIGVsIGN1cnNvIGRlIE1vZGVsb3MgRXN0YWTDrXN0aWNvcyBlbCBjb25qdW50byBkZSBkYXRvcywgKkNoZWRkYXIqLCBkaXN0cmlidWlkbyBlbiBsYSBsaWJyZXLDrWEgRmFyYXdheSBkZSBSLiBQYXJhIGVsbG8gaGVtb3MgdXRpbGl6YWRvIGRpdmVyc2FzIHTDqWNuaWNhcyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCnN1YnRpdGxlOiAnQ29uanVudG8gZGUgRGF0b3M6IENoZWRkYXIgRmFyYXdheScNCi0tLQ0KDQoNCiMgSW50cm9kdWNjacOzbg0KDQpFbiB1biBlc3R1ZGlvIGRlIHF1ZXNvIENoZWRkYXIgcmVhbGl6YWRvIGVuIGVsIFZhbGxlIGRlIExhdHJvYmUgKFZpY3RvcmlhLCBBdXN0cmFsaWEpLCBzZSBlc3R1ZGlhcm9uIG11ZXN0cmFzIGRlIHF1ZXNvIGVuIGxhcyBxdWUgc2UgYW5hbGl6w7Mgc3UgY29tcG9zaWNpw7NuIHF1w61taWNhIHkgZnVlcm9uIGRhZGFzIGEgcHJvYmFyIGEgZGlzdGludG9zIHN1amV0b3MgcGFyYSBxdWUgdmFsb3JhcmFuIHN1IHNhYm9yLiBMb3MgdmFsb3JlcyBhc2lnbmFkb3MgYSBjYWRhIHF1ZXNvIHNvbiBlbCByZXN1bHRhZG8gZGUgY29tYmluYXIgbGFzIGRpc3RpbnRhcyB2YWxvcmFjaW9uZXMuIA0KDQpFbCBEYXRhRnJhbWUgKipjaGVkZGFyKiogZGUgbGEgbGlicmVyw61hICoqZmFyYXdheSoqIGNvbnNpc3RlIGRlIDMwIG11ZXN0cmFzIGRlIHF1ZXNvIENoZWRkYXIgZW4gbGFzIHF1ZSBzZSBoYSBtZWRpZG8gZWwgc2Fib3IgKCp0YXN0ZSopIHkgbGFzIGNvbmNlbnRyYWNpb25lcyBkZSDDoWNpZG8gYWPDqXRpY28gKCpBY2V0aWMqKSwgw6FjaWRvIHN1bGZow61kcmljbyAoKkgyUyopIHkgbGFjdG9zYSAoKkxhY3RpYyopLg0KDQoNClRlbmVuZW1vcyB1biBjb25qdW50byBkZSBkYXRvcyBlbiBlbCBxdWUgc2UgcmVjb2dlbiBvYnNlcnZhY2lvbmVzIGRlIHVuYSBjYXRhIGRlDQpxdWVzb3MsIG51ZXN0cmFzIHZhcmlhYmxlcyBzb246ICAgDQoNCg0KKirCtyBUYXN0ZToqKiB1bmEgdmFsb3JhY2nDs24gc3ViamV0aXZhIGRlIGxvcyBqdWVjZXMuICAgDQoNCioqwrcgQWNldGljOioqIGxhIGNvbmNlbnRyYWNpw7NuIGRlIMOhY2lkbyBhY8OpdGljby4NCg0KKirCtyBIMlM6KiogbGEgY29uY2VudHJhY2nDs24gZGUgc3VsZml0byBkZSBoaWRyw7NnZW5vLg0KDQoqKsK3IExhY3RpYzoqKiBjb25jZW50cmFjacOzbiBkZSDDoWNpZG8gbMOhY3RpY28uDQoNCiA8IS0tIEEgbG8gbGFyZ28gZGVsIGRvY3VtZW50byBoYWNlbW9zIHVzbyBkZSBsYXMgc2lndWllbnRlcyBsaWJyZXJpYXMgZGUgUjogLS0+DQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KbGlicmFyeShmYXJhd2F5KQ0KbGlicmFyeShsZWFwcykNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkoUEFTV1IpDQpsaWJyYXJ5KGNhcikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShzY2F0dGVycGxvdDNkKQ0KbGlicmFyeShsbXRlc3QpDQpsaWJyYXJ5KG1peGxtKQ0KbGlicmFyeShjb3dwbG90KQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkobGVtb24pDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeSh0aWJibGUpDQpgYGANCg0KQ2FyZ2Ftb3MgbG9zIGRhdG9zIHkgZW5zZcOxYW1vcyBsYXMgcHJpbWVyYXMgb2JzZXJ2YWNpb25lcy4NCmBgYHtyIGVjaG89RkFMU0V9DQojIGxvYWQgY2hlZGRhciBjaGVkZGFyDQpkYXRhKGNoZWRkYXIpIA0KaGVhZChjaGVkZGFyKQ0KYGBgDQoNClNpIGVuIG51ZXN0cm8gZGF0YXNldCB0dXZpZXNlbW9zIGVudHJhZGFzIHZhY8OtYXMgKE5BKSwgdGVuZW1vcyB2YXJpYXMgcG9zaWJpbGlkYWRlcyBwYXJhIGxpZGlhciBjb24gZXN0ZSBwcm9ibGVtYToNCg0KKiBObyB1dGlsaXphci9FbGltaW5hciBsYXMgb2JzZXJ2YWNpw7NuIHF1ZSBjb250aWVuZW4gdmFsb3Jlcy4NCg0KKiBObyB1dGlsaXphci9FbGltaW5hciBsYXMgdmFyaWFibGVzIHF1ZSBjb250aWVuZW4gbGFzIGVudHJhZGFzIHZhY8OtYXMuDQoNCiogSW50ZW50YXIgY29tcGxldGFyIGxvcyB2YWxvcmVzLiBFeGlzdGVuIG3DqXRvZG9zIG1lbm9zIHkgbcOhcyBzb2Zpc2l0Y2Fkb3M6DQoNCiAgKyBSZW1wbGV6YXIgY29uIGxhICoqbWVkaWEsIG1lZGlhIG8gbW9kYSoqLg0KDQogICsgQ3JlYXIgdW5hICoqbnVldmEgY2F0ZWdvcsOtYSoqIHBhcmEgdmFsb3JlcyB2YWPDrW9zLg0KDQogICsgVXRpbGl6YXIgYWxnw7puIG1vZGVsbyBkZSAqKnJlZ3Jlc2nDs24qKi4NCg0KICArIFVzYXIgdW4gbW9kZWxvIGRlICoqSy1OZWFyZXN0IE5laWdoYm9ycyAoS05OKSoqLg0KICANClBlcm8gZW4gbnVlc3RybyBjYXNvIGV2YWx1YW1vcyB5IG5vIGhheSB2YWxvcmVzICptaXNzaW5nKi4gIA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBjaGVjayBpZiBhbnkgZW50cnkgaGFzIGEgbWlzc2luZyB2YWx1ZSAoTkEpDQphbnkoaXMubmEoY2hlZGRhcikpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2FwcGx5KGNoZWRkYXIsIGNsYXNzKQ0KYGBgDQoNCkVuIG51ZXN0cm8gY2FzbywgdG9kYXMgbGFzIHZhcmlhYmxlcyBzb24gbnVtw6lyaWNhcyAoKipjdWFudGl0YXRpdmFzKiopLiBObyBoYXkgbmluZ3VuYSB2YXJpYWJsZSBjYXRlZ8OzcmljYSBuaSBjdWFsaXRhdGl2YS4gU2kgaHViaWVzZSwgdGVuZHLDrWFtb3MgcXVlIHRyYW5zZm9ybWFybGFzIGVuIHZhcmlhYmxlcyBiaW5hcmlhcy4gUGFyYSBlbGxvLCBkZWJlcsOtYW1vcyBoYWNlciBlbmNvZGluZyBhIHZhcmlhYmxlcyBiaW5hcmlhcywgZWwgbGVuZ3VhamUgZGUgcHJvZ3JhbWFjacOzbiBSIG5vcyBwZXJtaXRlIHV0aWxpemFyICphcy5udW1lcmljKi4NCg0KQ29uIGVzdGFzIHZhcmlhYmxlcyB2YW1vcyBhIGludGVudGFyICoqZXhwbGljYXIqKiBjw7NtbyBsb3MgdmFsb3JlcyBvYnNlcnZhZG9zIGRlIHVuYSB2YXJpYWJsZSBZICh0YXN0ZSkgZGVwZW5kZW4gZGUgbG9zIHZhbG9yZXMgZGUgb3RyYXMgdmFyaWFibGVzIChBY2V0aWMsIEgyUywgTGF0Y2ljKSwgYSB0cmF2w6lzIGRlIHVuYSByZWxhY2nDs24gZnVuY2lvbmFsIGxpbmVhbCBkZWwgdGlwbyBZID0gZihYKS4NClRhbWJpw6luIHZhbW9zIGEgaW50ZW50YXIgKipwcmVkZWNpcioqIGVsIHZhbG9yIGRlIGxhIHZhcmlhYmxlIFkgcGFyYSB2YWxvcmVzIG5vIG9ic2VydmFkb3MgZGUgbGFzIHZhcmlhYmxlcyBYLg0KDQoNClRlbmVtb3MgMzAgb2JzZXJ2YWNpb25lcyBlbiBudWVzdHJvIGRhdGFzZXQuIEFob3JhIHByb2NlZGVtb3MgYSBkaXZpcmxvIGVuIGVsICpjb25qdW50byBkZSB0cmFpbiB5IHRlc3QqLiBFbCBwcmltZXJvIGxvIHV0aWxpemFyZW1vcyBwYXJhIGVudHJlbmFyIG51ZXN0cm9zIG1vZGVsb3MgeSBlbCBzZWd1bmRvIGxvIHVzYXJlbW9zIHBhcmEgY3VhbnRpZmljYXIgZWwgZXJyb3IgZGUgbG9zIG1vZGVsb3MuDQoNCg0KUGFyYSBhc2VndXJhciBxdWUgc2VhIHJlcHJvZHVjaWJsZSB1dGlsaXphbW9zIHVuYSBzZW1pbGxhLCBxdWUgcGVybWl0ZSBmaWphciBsb3MgdmFsb3JlcyBwc2V1ZG9hbGVhdG9yaW9zIG9idGVuaWRvcyBlbiBtdWNoYXMgZGUgbGFzIGZ1bmNpb25lcyB1dGlsaXphZGFzLg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgUGFyYSBhc2VndXJhciBxdWUgc2VhIHJlcHJvZHVjaWJsZSB1dGlsaXphbW9zIHVuYSBzZW1pbGxhLCBxdWUgcGVybWl0ZSBmaWphciBsb3MgdmFsb3JlcyBwc2V1ZG9hbGVhdG9yaW9zIG9idGVuaWRvcyBlbiBtdWNoYXMgZGUgbGFzIGZ1bmNpb25lcyB1dGlsaXphZGFzLg0Kc2V0LnNlZWQoMSkNCnRyYWluIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwNCiAgICAgICAgICAgICAgICBzaXplID0gbnJvdyhjaGVkZGFyKSwNCiAgICAgICAgICAgICAgICByZXBsYWNlID0gVFJVRSwNCiAgICAgICAgICAgICAgICBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0IDwtICF0cmFpbg0KYGBgDQoNCkhhY2Vtb3MgdW4gZXN0dWRpbyBwcmVsaW1pbmFyIGRlIG51ZXN0cmFzIHZhcmlhYmxlcy4gTW9zdHJhbW9zIHVuIHNjYXR0ZXIgcGxvdCBkZSBjYWRhIHZhcmlhYmxlIGNvbnRyYXN0YWRhIGNvbiBlbCByZXN0by4gRXN0byBwZXJtaXRlIHZlciAqYSBvam8qIHNpIGFsZ8O6biBwYXIgZGUgdmFyaWFibGVzIHRpZW5lIGNvcnJlbGFjacOzbi4gIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCxmaWcud2lkdGg9NyxmaWcuaGVpZ2h0PTR9DQpwbG90KGNoZWRkYXIpDQpgYGANCiAgDQogIEFob3JhLCB1dGlsaXphbW9zIGxhIGZ1bmNpw7NuICpzdW1tYXJ5KiBkZSBSLCBsYSBjdWFsIG5vcyBwZXJtaXRlIGVzdGltYXIgYWxndW5vcyBkZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsYSBkaXN0cmlidWNpw7NuIGRlbCBkYXRhc2V0LiBMYSBzaWd1aWVudGUgdGFibGEgbm9zIG11ZXN0cmEgbG9zIGVzdGFkw61zdGljb3MgbcOhcyBjb211bmVzOiBlbCBtw61uaW1vLCBtw6F4aW1vLCBtZWRpYW5hLCBtZWRpYSB5IGVsIDFlciB5IDNlciBjdWFydGlsLiANCg0KDQpgYGB7cixmaWcuaGVpZ2h0PTIsIGVjaG89RkFMU0UsZmlnLndpZHRoPTV9DQpzdW1tYXJ5KGNoZWRkYXIpICMgRGlzdHJpYnVjacOzbiBkZSBsYXMgdmFyaWFibGVzDQpgYGANCg0KDQpgYGB7ciBBdHRhY2gsIGluY2x1ZGU9RkFMU0V9DQphdHRhY2goY2hlZGRhcikNCmBgYA0KDQoNCkhhY2Vtb3MgbGFzIGdyw6FmaWNhcyBkZSBkaXNwZXJzacOzbiBlbnRyZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgKnRhc3RlKiB5IGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgKkFjZXRpYywgSDJTLCBMYWN0aWMqLg0KDQpgYGB7ciBlY2hvPUZBTFNFLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9M30NCmxheW91dChtYXRyaXgoMTozLCBucm93ID0gMSkpDQojIHBsb3QgdGFzdGUgfiBBY2V0aWMNCnBsb3QoQWNldGljLCB0YXN0ZSwNCiAgICAgbWFpbiA9ICJSZWxhY2nDs24gZW50cmUgVGFzdGUgeSBBY2V0aWMiLA0KICAgICB4bGFiID0gIkFjZXRpYyIsIHlsYWIgPSAiVGFzdGUiLA0KICAgICBwY2ggPSAxOSwgZnJhbWUgPSBGQUxTRSkNCiMgcGxvdCB0YXN0ZSB+IEgyUw0KcGxvdChIMlMsIHRhc3RlLA0KICAgICBtYWluID0gIlJlbGFjacOzbiBlbnRyZSBUYXN0ZSB5IEgyUyIsDQogICAgIHhsYWIgPSAiSDJTIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KIyBwbG90IHRhc3RlIH4gTGFjdGljDQpwbG90KExhY3RpYywgdGFzdGUsDQogICAgIG1haW4gPSAiUmVsYWNpw7NubiBlbnRyZSBUYXN0ZSB5IExhY3RpYyIsDQogICAgIHhsYWIgPSAiTGFjdGljIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpsYXlvdXQobWF0cml4KDE6MSwgbnJvdyA9IDEpKQ0KYGBgDQoNClBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGxhIHF1ZSBhcGVyZW50ZW1lbnRlIGd1YXJkYSB1bmEgbWVub3IgcmVsYWNpw7NuIGxpbmVhbCBjb24gdGFzdGUgZXMgbGEgdmFyaWFibGUgQWNldGljLCBlc3RlIGhlY2hvIHNlcsOhIHJlYWZpcm1hZG8gbcOhcyBhZGVsYW50ZS4NCg0KDQojIEVzdHVkaW8geSBldmFsdWFjacOzbiBkZWwgbW9kZWxvIGNvbXBsZXRvLiAgDQoNCkludGVudGFyZW1vcyBwcmVkZWNpciBsYSB2YXJpYWJsZSAqdGFzdGUqIHVzYW5kbyBlbCByZXN0byBkZSB2YXJpYWJsZXMuIFBhcmEgZW1wZXphciwgZGVmaW5pbW9zIGVsIG1vZGVsbyBjb21wbGV0bywgZWwgY3VhbCBzZSB1c2FuIHRvZGFzIGxhcyB2YXJpYWJsZXMgcGFyYSBudWVzdHJvIG1vZGVsbyBsaW5lYWwgbcO6bHRpcGxlLg0KDQokJA0KWV9pID1cYmV0YV8wICsgXGJldGFfMSB4X3tpMX0gKyBcZG90cyArIFxiZXRhX3twLTF9eF97aShwLTEpfSArIFxlcHNpbG9uX2ksXHF1YWQgaT0xLFxkb3RzLG4NCiQkDQpkb25kZSAkWV9pJCBlcyBlbCB2YWxvciBkZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgcGFyYSBlbCBpbmRpdmlkdW8gJGkkLcOpc2ltbywgDQokXGJldGFfMCQgeSBsb3MgJFxiZXRhX2okIHNvbiBsb3MgcGFyw6FtZXRyb3MgJGogPSAxLCAuLi4sIHAgLSAxJCwgDQokeF97aWp9JCBzb24gbG9zIGVsZW1lbnRvcyBkZSBsYSBtYXRyaXogZGUgbGFzIHZhcmlhYmxlcyBleHBsaWNhdGl2YXMgDQokXGVwc2lsb25faSQgZXMgZWwgdMOpcm1pbm8gZGVsIGVycm9yIGFsZWF0b3JpbyBxdWUgc3Vwb25lbW9zIHF1ZSBzZSBkaXN0cmlidXllIGNvbW8gdW5hICRcbWF0aGNhbHtOfSgwLFxzaWdtYV4yKSQsIGRvbmRlICRcc2lnbWFeMiQgZXMgbGEgdmFyaWFuemEgcXVlIHN1ZWxlIHNlciBkZXNjb25vY2lkYS4NCg0KIyMgUmVzb2x1Y2nDs24gbWVkaWFudGUgbWF0cmljZXMNCg0KVXRpbGl6YW1vcyBlbCBtw6l0b2RvIGRlIG3DrW5pbW9zIGN1YWRyYWRvcyBxdWUgZXN0aW1hIGxvcyB2YWxvcmVzICRcaGF0e1xiZXRhfSQgaW50ZW50YW5kbyBtaW5pbWl6YXIgbG9zIGVycm9yZXMgJFxlcHNpbG9uJC4gQ29tbyBoZW1vcyB2aXN0byBlbiBjbGFzZSwgbGEgZsOzcm11bGEgcXVlIHNlIGRlZHVjZSBlczoNCg0KJCQgDQpcaGF0e1xiZXRhfSA9IChYXnRYKV57LTF9WF50WQ0KJCQNCmRvbmRlICRYJCBlcyB1bmEgY29sdW1uYSBkZSAxJ3MgY29uY2F0ZW5hZGEgY29uIGxhcyB2YXJpYWJsZXMgcXVlIHVzYW1vcyBwYXJhIHByZWRlY2lyLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KeCA8LSBtb2RlbC5tYXRyaXgoIH4gQWNldGljICsgSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhcikNCmJldGFoYXQgPC0gc29sdmUoY3Jvc3Nwcm9kKHgsIHgpLCBjcm9zc3Byb2QoeCwgdGFzdGUpKQ0KYmV0YWhhdCA8LSBjKGJldGFoYXQpDQpiZXRhaGF0DQpgYGANClBvciB0YW50bywgYXByb3hpbWFtb3MgbGFzICRcYmV0YSQgbW9kZWxvIGxpbmVhbCBjb21wbGV0byBjb24gbG9zIHZhbG9yZXMgZGUgJFxoYXR7XGJldGF9XzAsXGRvdHMsXGhhdHtcYmV0YX1fMyQgY29uIGxvcyBzaWd1aWVudGVzIHZhbG9yZXM6DQoNCiQkDQpcaGF0e1xiZXRhfV8wPS0yOC44NzY3Njk2LFxxdWFkXGhhdHtcYmV0YX1fMT0wLjMyNzc0MTMsXHF1YWRcaGF0e1xiZXRhfV8yPTMuOTExODQxLFxxdWFkXGhhdHtcYmV0YX1fMz0xOS42NzA1NDM0DQokJA0KDQojIyBSZXNvbHVjacOzbiB1c2FuZG8gbGlicmVyaWFzIGRlIFINCg0KUG9kZW1vcyB1dGlsaXphciBsYSBmdW5jacOzbiAkbG0kLCB5YSBwcm9ncmFtYWRhIGVuIFIuIERlZmluaW1vcyBlbCBtb2RlbG8gY29tcGxldG8sIHkgY29tcHJvYmFtb3MgbGFzIGJldGFzOg0KDQokJA0KdGFzdGUgXHNpbSBBY2V0aWMgXCwgKyBcLCBIMlMgXCwgKyBcLCBMYWN0aWMsIFwsICBcLCBkYXRhID0gY2hlZGRhcg0KJCQNCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuYWxsLmxtIDwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXIpDQoNCmZpbGFfY29lZiA8LSB2ZWN0b3IoKQ0KZGZfYW5vdmEgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCAiMiIgPSAyLCIzIiA9IDMsIjQiPTQsIHJvdy5uYW1lcyA9ICJDb2VmaWNpZW50ZXMiKQ0KY29sbmFtZXMoZGZfYW5vdmEpIDwtIGMoIkludGVyY2VwdCIsIkFjZXRpYyIsIkgyUyIsIkxhY3RpYyIpDQoNCmZvcihpIGluIDE6NCl7DQpmaWxhX2NvZWYgPC0gYyhmaWxhX2NvZWYsbW9kZWwuYWxsLmxtJGNvZWZmaWNpZW50c1tbaV1dKSAgDQp9DQoNCmRmX2Fub3ZhWzEsXSA8LSBmaWxhX2NvZWYNCmRmX2Fub3ZhDQoNCmBgYA0KDQoNCkVzdHVkaWVtb3MgcHJlbGltaW5hcm1lbnRlIHNpIGVzIHVuIG1vZGVsbyBsaW5lYWwgYWRlY3VhZG8sIHBhcmEgZWxsbyANCmNvbXByb2JhcmVtb3MgbGFzIGhpcMOzdGVzaXMgZXN0w6FuZGFyIGRlbCBtb2RlbG8gbGluZWFsIGRlIHJlZ3Jlc2nDs24gdXNhbmRvIGVsICoqdGVzdCBkZSBub3JtYWxpZGFkIFNoYXBpcm8tV2lsayoqLiBMYSBmdW5jacOzbiAkc2hhcGlyby50ZXN0JCBsZSBwYXNhbW9zIHBvciBwYXLDoW1ldHJvIGVsIHJlc2lkdW8vZXJyb3IgZGUgY2FkYSB1bmEgZGUgbGFzIG11ZXN0cmFzIHkgbm9zIGRldnVlbHZlIHVuICRwJC12YWxvci4NCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLmFsbC5sbSkpDQpgYGANCk9ic2VydmFtb3MgcXVlIGVzdGFtb3MgZW4gbGEgaGlww7N0ZXNpcyBkZSBxdWUgZWwgZXJyb3IgbnVlc3RybyBtb2RlbG8gc2UgZGlzdHJpYnV5ZSBkZSBtYW5lcmEgbm9ybWFsLCB5YSBxdWUgZWwgcC12YWxvciBlcyAkMC44ODY1ID4gMC4wNSQuIA0KDQpPdHJvIGFzcGVjdG8gcXVlIGRlYmVtb3Mgc2FiZXIgZXMgc2kgbGEgbWVkaWEgZGUgbG9zIGVycm9yZXMgc2Vyw6EgbnVsYSBvIG5vLCBwYXJhIGVsbG8gdXNhbW9zIHVuYSBmdW5jacOzbiBpbXBsZW1lbnRhZGEgZW4gUiBxdWUgbm9zIGFmaXJtYSBxdWUgZW4gbnVlc3RybyBjYXNvIGVzdG8gZXMgYXPDrS4gUmVzcGVjdG8gYSBsb3MgZXJyb3JlcyB0ZW5lbW9zIHF1ZSBzYWJlciBxdWUgc2UgZGlzdHJpYnV5ZW4gY29uIHZhcmlhbnphIGNvbnN0YW50ZSwgcXVlIGRlIG1hbmVyYSBhbsOhbG9nYSBjb21wcm9iYW1vcywgdGVuaWVuZG8gcC12YWxvcmVzIGxvIHN1ZmljaWVudGVtZW50ZSBiYWpvcyBjb21vIHBhcmEgcmVjaGF6YXIgdmFyaWFuemEgbm8gY29uc3RhbnRlLg0KIERlIGlndWFsIG1hbmVyYSB0ZW5lbW9zIHF1ZSBubyBoYXkgYXV0b2NvcnJlbGFjacOzbiBlbiBlbCBtb2RlbG8gY29tcGxldG8uDQoNClVuYSB2ZXogaGVtb3MgY29uY2x1aWRvIHF1ZSBhdW5xdWUgZXN0YW1vcyBlbiBsYXMgaGlww7N0ZXNpcyBkZSByZWdyZXNpw7NuIGxpbmVhbA0KZWwgbW9kZWxvIGNvbXBsZXRvIGEgcGVzYXIgZGUgc2VyIGVsIG3DoXMgY29tcGxlam8gcHJvYmFibGVtZW50ZSBkYSByZXN1bHRhZG9zIA0Kc2ltaWxhcmVzIGEgb3RybyBtw6FzIHNpbXBsZS4NCg0KYGBge3IgZWNobz1GQUxTRX0NCnN1bW1hcnkobW9kZWwuYWxsLmxtKQ0KYGBgDQpUcmFzIHJlYWxpemFyIGVsIHN1bW1hcnkgZGVsIG1vZGVsbywgdW5hIG9ic2VydmFjacOzbiBtdXkgaW1wb3J0YW50ZSBxdWUgc2FjYW1vcyBlcyBxdWUgZWwgcC12YWxvciBkZSBBY2V0aWMgZXMgbXV5IGdyYW5kZSAoMC45NCkgcG9yIGxvIHF1ZSBubyB2YSBhIHNlciB1bmEgdmFyaWFibGUgc2lnbmlmaWNhdGl2YSB5IHBvciB0YW50byBjb24gY2FzaSB0b2RhIHNlZ3VyaWRhZCBubyB0aWVuZSBpbXBhY3RvIHJlYWwgZW4gZWwgbW9kZWxvLg0KDQpQb3IgZWwgY29udHJhcmlvIGVsIHJlc3RvIGRlIHZhcmlhYmxlcyBzw60gc29uIHNpZ25pZmljYXRpdmFzIHBvciB0ZW5lciBwLXZhbG9yIGluZmVyaW9yIGEgMC41LCBkZXN0YWNhbmRvIExhY3RpYyBwb3IgdGVuZXIgdW4gYmV0YSBtYXlvciBxdWUgSDJTLCBsbyBxdWUgcHB1ZWRlIGhhY2Vybm9zIGxsZWdhciBhIHBlbnNhciBxdWUgY29icmUgbcOhcyBpbXBvcnRhbmNpYSBlbiB1biBtb2RlbG8gZmluYWwuDQojIyMjIENvcnJlbGFjaW9uZXMgeSB0YWJsYSBkZSByZXN1bHRhZG9zIGNvbiBlbCBlc3R1ZGlvIGRlIHN1cyBwLXZhbG9yZXMNClVzYW1vcyBlbCBwYXF1ZXRlICRHR3Bsb3QkIGRlIFIsIGVsIGN1YWwgbm9zIHBlcm1pdGUgdmlzdWFsaXphciBsYSBjb3JyZWxhY2nDs24geSBkaXNwZXJzacOzbiBlbnRyZSBsYXMgZGlzdGludGFzIHZhcmlhYmxlcy4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0zLjUsIGZpZy53aWR0aD03LCBtZXNzYWdlPUZBTFNFfQ0KY29ycGxvdCA8LSBnZ3BhaXJzKGNoZWRkYXJbdHJhaW4sXSwgcHJvZ3Jlc3M9RkFMU0UpDQpjb3JwbG90IA0KYGBgDQoNClBkZW1vcyBhcHJlY2lhciBxdWUgbGEgdmFyaWFibGUgY29uIG1lbm9yIGNvZWZlY2llbnRlIGRlIGNvcnJlbGFjacOzbiBkZSBQZWFyc29uIGVzIEFjZXRpYyxtaWVudHJhIHF1ZSBlbCByZXN0byBkZSB2YXJpYWJsZXMgdGllbmVuICB1biB2YWxvciBiYXN0YW50ZSBtYXlvci4gQ2FiZSBkZXN0YWNhciBxdWUgdG9kb3MgdGllbmVuIHVuIHNpZ25vIHBvc2l0aXZvLCBsbyBxdWUgbm9zIGRpY2UgcXVlIGVuIGdlbmVyYWwgYWwgYXVtZW50YXIgdW5hIGF1bWVudGEgbGEgb3RyYS4NCg0KDQojIyDCv1RpZW5lICpvdXRsaWVycyogbnVlc3RyYSBtdWVzdHJhPw0KDQpQYXJhIGNvbXByb2JhcmxvIGJhc3RhIHJlYWxpemFyIGVsICoqdGVzdCBkZSBCb25mZXJyb25pKiogc29icmUgbnVlc3RybyBtb2RlbG8gY29tcGxldG86DQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpvdXRsaWVyVGVzdChtb2RlbC5hbGwubG0pDQpgYGANCg0KDQpDb25jbHVpbW9zIGNvbiB1biBuaXZlbCAkXGFscGhhJCA9IDAuMDUgcXVlIG5vIHRlbmVtb3MgbmluZ8O6biBvdXRsaWVyIGVuIG51ZXN0cmEuIExvIG3DoXMgY2VyY2FubyBhIHVuICpvdXRsaWVyKiBxdWUgdGVuZW1vcyBlcyBsYSBvYnNlcnZhY2nDs24gbsO6bWVybyAxNSwgcXVlIHRpZW5lIHVuIHZhbG9yICoqQm9uZmVycm9uaSBwKiogZGUgMC4xNzQ1MyAobm8gc2UgYWNlcmNhIGEgMC4wNSkuIFBvciB0YW50bywgbm8gdGVuZW1vcyByYXpvbmVzIHBvciBsYXMgcXVlIGVsaW1pbmFyIGFsZ3VuYSBvYnNlcnZhY2nDs24gaW51c3VhbCBkZSBudWVzdHJvIGNvbmp1bnRvIGRlIGRhdG9zLiANCg0KRXN0byBzZSBwdWVkZSBjb21wcm9iYXIgZ3JhZmljYW1lbnRlIGEgdHJhdsOpcyBkZWwgc2lndWllbnRlIGdyw6FmaWNvLCBlbCBjdWFsIG1pZGUgbGEgaW5mbHVlbmNpYSBkZSBjYWRhIG9ic2VydmFjacOzbiBzb2JyZSBjYWRhIHVuYSBkZSBsYXMgYmV0YXMgZGUgbnVlc3RybyBtb2RlbG8uIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMuNn0NCmluZmx1ZW5jZUluZGV4UGxvdChtb2RlbC5hbGwubG0pDQpgYGANCg0KVmVtb3MgcXVlIGxhIHF1ZSBtw6FzIGluZmx1eWUgZXMgbGEgYW50ZXMgbWVuY2lvbmFkYSBvYnNlcnZhY2nDs24gMTUgeSBwb3IgdGFudG8gZGViZXLDrWFtb3MgY29uc2lkZXJhciBzaSBlcyBvdXRsaWVyLiBIZW1vcyBjb21wcm9iYWRvIHF1ZSBzdWNlZGVyw61hIGFsIGVsaW1pbmFyIGVzYSBvYnNlcnZhY2nDs24gZGUgbGEgbXVlc3RyYSwgeSBzaSBiaWVuIG1lam9yYWJhIGFsZ8O6biBwLXZhbG9yIGRlIGxhcyBoaXDDs3Rlc2lzIGRlIHJlZ3Jlc2nDs24sIGVuIG90cm9zIGxvcyBlbXBlb3JhYmEsIGFzw60gcXVlIGhlbW9zIGRlY2lkaWRvIG5vIGVsaW1pbmFybGEgeSBlc3BlcmFybm9zIGEgdmVyIGVsIGNhc28gZW4gbGFzIHNlZWRzIHF1ZSBlc3R1ZGlhcmVtb3MgY29uIG3DoXMgZGV0YWxsZXMgc2kgc2FsZSBkZSBsYSBtdWVzdHJhIGNvbW8gb2JzZXJ2YWNpw7NuIGluZmx1eWVudGUuIA0KDQojIMK/Q3XDoWwgZXMgZWwgbWVqb3IgbW9kZWxvPw0KDQpDb21vIGRpY2UgZWwgKipQcmluY2lwaW8gZGUgbGEgTmF2YWphIGRlIE9ja2hhbSoqLCBhIG1lbnVkbyBsYSBleHBsaWNhY2nDs24gbcOhcyBzaW1wbGUgZXMgbGEgY29ycmVjdGEuIFF1ZXJlbW9zIHNlbGVjY2lvbmFyIHByZWRpY3RvcmVzIHF1ZSBleHBsaWNhbiBsb3MgZGF0b3MgZGUgbGEgbWFuZXJhIG3DoXMgc2ltcGxlIHBvc2libGUsIHNpbiBkaXNtaW51aXIgbGEgY2FsaWRhZCBkZSBsYXMgcHJlZGljY2lvbmVzIG11Y2hvLg0KDQojIyMgU2VwYXJhY2lvbiBkZWwgZGF0YXNldCBlbiBjb25qdW50b3MgZGUgZW50cmVuYW1pZW50byB5IHRlc3QgKDcwLTMwJSkgIA0KDQpIZW1vcyBlc2NvZ2lkbyBkaXN0aW50YXMgc2VtaWxsYXMgcGFyYSBlc3RhciBlbiBjb25kaWNpb25lcyBkZSByZWFsaXphciB1biBlc3R1ZGlvIG3DoXMgYW1wbGlvLCBlbiBsYSBlbGVjY2nDs24gZGUgbGFzIG1pc21hcyBzZSBoYSBpbnRlbnRhZG8NCmV2aXRhciBhcXVlbGxhcyBxdWUgZ2VuZXJhYmFuIG11ZXN0cmFzIGRlbWFzaWFkbyBzaW1pbGFyZXMuIExhcyBzZW1pbGxhcyB1c2FkYXMgc29uIDEsIDExMDAgeSA1IHBvc3Rlcmlvcm1lbnRlIHNlIGludHJvZHVjaXLDoW4gZG9zIG3DoXMgcGFyYSBhZmluYXIgZW4gZWwgY8OhbGN1bG8gZGUgZXJyb3Jlcy4NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnNldC5zZWVkKDEpIA0KdHJhaW4uMSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4xIDwtICghdHJhaW4uMSkNCnN1bSh0ZXN0LjEpDQptb2RlbC5hbGwxIDwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKQ0Kc2V0LnNlZWQoMTEwMCkgDQp0cmFpbi4yIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0LjIgPC0gKCF0cmFpbi4yKQ0Kc3VtKHRlc3QuMikNCnN1bSh0ZXN0LjE9PVRSVUUgJiB0ZXN0LjI9PVRSVUUpI3NvbG8gMSBwcmVzZWd1aW1vcw0KbW9kZWwuYWxsMiA8LSBsbSh0YXN0ZSB+IC4sIGRhdGEgPSBjaGVkZGFyW3RyYWluLjIsXSkNCnNldC5zZWVkKDUpIA0KdHJhaW4uMyA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4zIDwtICghdHJhaW4uMykNCnN1bSh0ZXN0LjMpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC4zPT1UUlVFKQ0Kc3VtKHRlc3QuMj09VFJVRSAmIHRlc3QuMz09VFJVRSkNCm1vZGVsLmFsbDMgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0pDQpgYGANCkNvbnNpZGVyZW1vcyBsb3MgY29uanVudG9zIGRlIGVudHJlbmFtaWVudG8gcmVzdWx0YW50ZXMgZGUgbGFzIHNlbWlsbGFzOiAqdHJhaW4uMSooc2VtaWxsYSAxKSwgKnRyYWluLjIqKHNlbWlsbGEgMTEwMCksICp0cmFpbi4zKihzZW1pbGxhIDUpLlZlYWFtb3MgcXVlIG1vZGVsb3MgZGViZW1vcyBjb25zaWRlcmFyIGVuIGJhc2UgYSBudWVzdHJvcyB0cmFpbi4NCg0KIyMjIE3DqXRvZG8gQmFja3dhcmQNCg0KUGFydGltb3MgZGVsIG1vZGVsbyBjb21wbGV0byBlc3R1ZGlhZG8gZW4gbGEgc2VjY2nDs24gYW50ZXJpb3IsIGVzbyBzw60sIGV2YWx1YWRvIGVuIG51ZXN0cm9zIHJlc3BlY3Rpdm9zIHRyYWluIHkgYXBsaWNhbW9zIGNvbiAkXGFscGhhJCA9IDAuMDUsIGVsIG3DqXRvZG8gZGUgQmFja3dhcmQsIHF1ZSBjb25zaXN0ZSBlbiBlbGltaW5hciBsYSB2YXJpYWJsZSBxdWUgKm1lbm9zIGluZmx1eWEqIGEgbGEgcHJlZGljY2nDs24uIFByaW1lcm8gcmVhbGl6YW1vcyB1bmEgaXRlcmFjacOzbiBleHBsw61jaXRhIGRlbCBtw6l0b2RvIHNvYnJlIGxhIHByaW1lcmEgc2VtaWxsYSwgeSBwb3N0ZXJpb3JtZW50ZSBzZSBjb25zdHJ1eWVuIGEgdHJhdsOpcyBkZSAgbGEgbGlicmVyaWEgKm1peGxtKiBkZSBSLiANCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KIyBkcm9wMShtb2RlbC5hbGwubG0sIHRlc3QgPSAiRiIpW1s2XV0NCmZpbGFfcHZhbG9yZXMgPC0gYygwLjMzNjI3LCAwLjA0MzE4LCAwLjAyMzY1ICkNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIjMiID0gMywgcm93Lm5hbWVzID0gInAtdmFsb3IiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJBY2V0aWMiLCJIMlMiLCJMYWN0aWMiKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX3B2YWxvcmVzDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQpFbGltaW5hbW9zIEFjZXRpYyBkZWwgbW9kZWxvIGRlYmlkbyBxdWUgc3UgcC12YWxvciBlcyA+MC4wNS4gIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQptb2RlbC5iYWNrd2FyZCA8LSB1cGRhdGUobW9kZWwuYWxsLmxtLCAuIH4gLiAtIEFjZXRpYykNCiMgZHJvcDEobW9kZWwuYmFja3dhcmQsIHRlc3QgPSAiRiIpW1s2XV0NCmZpbGFfcHZhbG9yZXMgPC0gYygwLjA1MTIyICwgMC4wMzI3NSkNCmRmX3B2YWxfZHJvcF9wMiA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIHJvdy5uYW1lcyA9ICJwLXZhbG9yIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMikgPC0gYygiSDJTIiwiTGFjdGljIikNCmRmX3B2YWxfZHJvcF9wMlsxLF0gPC0gZmlsYV9wdmFsb3Jlcw0KZGZfcHZhbF9kcm9wX3AyDQpgYGANClJlcGV0aW1vcyBlbCBwcm9jZXNvIGNvbiBsYSB2YXJpYWJsZSBIMlMsIHlhIHF1ZSB0aWVuZSB1biBwLXZhbG9yIG1heW9yIHF1ZSAkXGFscGhhID0gMC4wNSQNCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuYmFja3dhcmQgPC0gdXBkYXRlKG1vZGVsLmJhY2t3YXJkLCAuIH4gLiAtIEgyUykNCiNkcm9wMShtb2RlbC5iYWNrd2FyZCwgdGVzdCA9ICJGIikNCmZpbGFfcHZhbG9yZXMgPC0gYygxLjM4OGUtMDUpDQpkZl9wdmFsX2Ryb3BfcDMgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCByb3cubmFtZXMgPSAicC12YWxvciIpDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDMpIDwtIGMoIkxhY3RpYyIpDQpkZl9wdmFsX2Ryb3BfcDNbMSxdIDwtIGZpbGFfcHZhbG9yZXMNCmRmX3B2YWxfZHJvcF9wMw0KYGBgDQoNCkVsIHAtdmFsb3IgZXMgbWVub3IgcXVlICRcYWxwaGEgPSAwLjA1JCwgcG9yIGxvIHF1ZSBoZW1vcyBjb25jbHVpZG8sIHlhIHF1ZSBubyB0ZW5lbW9zIHN1ZmljaWVudGUgY2VydGV6YSBwYXJhIHBvZGVyIGVsaW1pbmFyIG90cmEgdmFyaWFibGUuUG9yIHRhbnRvLCB0ZW5lbW9zIGNvbW8gcmVzdWx0YWRvIHF1ZSBsYSB2YXJpYWJsZSBxdWUgbWVqb3IgZXhwbGljYSBlbCAqdGFzdGUqIGVzICpMYWN0aWMqLiBNb2RlbG8gcmVzdWx0YW50ZTogKip0YXN0ZSAgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSoqLiAgDQoNClBvciBvdHJvIGxhZG8gbG9zIG1vZGVsb3MgYmFja3dhcmQgcmVzdWx0YW50ZXMgcG9yICptaXhsbSogc29uOiAgDQoNCioqdGFzdGUgIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0qKiB5IHBvciBvdHJvIGxhZG8gKip0YXN0ZSAgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjMsXSoqLg0KDQojIyMgTcOpdG9kbyBGb3J3YXJkIA0KDQpFbCBtw6l0b2RvIEZvcndhcmQgY29uc2lzdGUgZW4gZW1wZXphciBjb24gdW4gbW9kZWxvIGRlIHVuYSB2YXJpYWJsZSB5IHZhbW9zIGHDsWFkaWVuZG8gbGFzIHF1ZSBtw6FzIGluZmx1eWFuLCBkZXNhcnJvbGxhcmVtb3MgZWwgcHJpbWVyIG1vZGVsbyBkZSBmb3JtYSBleHBsw61jaXRhIHkgZWwgcmVzdG8gbG9zIGdlbmVyYXJlbW9zIGNvbiAqbWl4bG0qLiAgRGUgZXN0YSBtYW5lcmEgdGVuZW1vczogIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQpTQ09QRTwtKH4uK0FjZXRpYyArIEgyUyArIExhY3RpYykNCm1vZGVsLmZvcndhcmQubG0gPC0gbG0odGFzdGV+MSxkYXRhPSBjaGVkZGFyW3RyYWluLF0pDQojYWRkMShtb2RlbC5mb3J3YXJkLmxtLHNjb3BlPVNDT1BFLHRlc3Q9IkYiKVtbNl1dDQpmaWxhX3B2YWxvcmVzIDwtIGMoMS4yNTE3ODZlLTAyLCAyLjExNTQ3M2UtMDUsIDEuMzg3OTIzZS0wNSkNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIjMiID0gMywgcm93Lm5hbWVzID0gInAtdmFsb3IiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJBY2V0aWMiLCJIMlMiLCJMYWN0aWMiKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX3B2YWxvcmVzDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KQWN0dWFsaXphbW9zIGHDsWFkaWVuZG8gTGFjdGljIHBvciB0ZW5lciBlbCBtZW5vciBwLXZhbG9yLg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuZm9yd2FyZC5sbSA8LSB1cGRhdGUobW9kZWwuZm9yd2FyZC5sbSwgLn4uICsgTGFjdGljKQ0KIyBhZGQxKG1vZGVsLmZvcndhcmQubG0sc2NvcGU9U0NPUEUsdGVzdD0iRiIpW1s2XV0NCmZpbGFfcHZhbG9yZXMgPC0gYygwLjUwMzk4Nzc0ICwwLjA1MTIxNzExNSkNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIHJvdy5uYW1lcyA9ICJwLXZhbG9yIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gYygiQWNldGljIiwiSDJTIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9wdmFsb3Jlcw0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCkNvbiBuaXZlbCBkZSBzaWduaWZpY2FjacOzbiAkXGFscGhhJCA9IDAuMDUgZXN0ZSBzZXLDrWEgbnVlc3RybyBtb2RlbG8gZmluYWwuIE1vZGVsbyByZXN1bHRhbnRlID0gKip0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKiogIA0KUG9yIG90cm8gbGFkbyBsb3MgbW9kZWxvcyBmb3J3YXJkIHJlc3VsdGFudGVzIHBvciAqbWl4bG0qIHNvbjogIA0KDQoqKnRhc3RlICB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMixdKiogeSBwb3Igb3RybyBsYWRvICoqdGFzdGUgIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0qKi4NCg0KIyMgQ29uc3RydWNjacOzbiBwb3IgY3JpdGVyaW9zDQoNCkVuIGVzdGEgc3Vic2VjY2nDs24gdHJhdGFyZW1vcyBkZSBlbmNvbnRyYXIgdW4gY2FuZGlkYXRvIGEgbWVqb3IgbW9kZWxvLCBjb25zdHJ1eWVuZG8gbnVlc3Ryb3MgbW9kZWxvcyB1c2FuZG8gZGlzdGludG9zIGVuZm9xdWVzLiBUcmFzIGFwbGljYXINCmxvcyBzaWd1aWVudGVzIGNyaXRlcmlvcyBhIGxhIGhvcmEgZGVsIGRlc2Fycm9sbG8gZGUgbW9kZWxvczogJFJeMiQgYWp1c3RhZG8sIENwIGRlIE1hbGxvd3MsIENyaXRlcmlvIGRlIEluZm9ybWFjaW9uIGRlIEJheWVzIChCSUMpLCBDcml0ZXJpbyBkZSBJbmZvcm1hY2lvbiBkZSBBa2Fpa2UgKEFJQykgZWxpZ2llbmRvIGVsIHF1ZSBub3MgZGUgdW4gbWVub3IgbyBtYXlvciBjb2VmaWNpZW50ZSBzZWfDum4gZWwgbcOpdG9kbyAobG9zIGRlc2Fycm9sb3Mgc2UgcHVlZGVuIGVuY29udHJhciBlbiBlbCBzY3JpcHQpLCBsbGVnYW1vcyBhIGxhcyBzaWd1aWVudGVzIGNvbmNsdXNpb25lczogIA0Kc29sbyBhcGFyZWNlIHVuIG1vZGVsbyBudWV2byB1c2FuZG8gZWwgY3JpdGVyaW8gZGVsIGVzdGFkw61zdGljbyAkUl4yJCBwYXJhIGxhIHByaW1lcmEgc2VtaWxsYSwgKip0YXN0ZSAgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSoqLiAgDQpOb3RhbW9zIHF1ZSBsYSBjb21iaW5hY2nDs24gZGUgSDJTICsgTCBhcGFyZWNlIGVuIHRvZG9zIG51ZXN0cm9zIGNvbmp1bnRvcyBkZSBlbnRyZW5hbWllbnRvIGVuIGFsZ8O6biBtb21lbnRvLCBlcyBjYW5kaWRhdGEgYSBzZXIgbnVlc3RyYSBtZWpvciBlbGVjY2nDs24uICANCg0KQ29tcGFyYW1vcyBsb3MgbW9kZWxvcyBvYnRlbmlkb3MgaGFzdGEgYWhvcmEgZW4gc3UgcmVzcGVjdGl2YSBtdWVzdHJhIGRlIGVudHJlbmFtaWVudG8gY29uIGVsIG1vZGVsbyBjb21wbGV0byBlbiBlc2UgY29uanVudG8gZGUgZW50cmVuYW1pZW50by4NCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQptb2RlbC4xIDwtIGxtKHRhc3RlIH4gTGFjdGljLCAgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkNCm1vZGVsLjFjcml0IDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKQ0KbW9kZWwuMiA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgIGRhdGE9Y2hlZGRhclt0cmFpbi4yLF0pDQptb2RlbC4zIDwtIGxtKHRhc3RlIH4gSDJTICtMYWN0aWMsICBkYXRhPWNoZWRkYXJbdHJhaW4uMyxdKQ0KIyBhbm92YShtb2RlbC4xLG1vZGVsLmFsbDEpW1s2XV0NCiMgYW5vdmEobW9kZWwuMWNyaXQsbW9kZWwuYWxsMSlbWzZdXQ0KIyBhbm92YShtb2RlbC4yLG1vZGVsLmFsbDIpDQojIGFub3ZhKG1vZGVsLjMsbW9kZWwuYWxsMylbWzZdXQ0KZmlsYV9wdmFsb3JlcyA8LSBjKDAuMDk4MjE0NTMsDQogICAgICAgICAgICAgICAgICAgMC4zMzYyNjg5LA0KICAgICAgICAgICAgICAgICAgIDAuOTU1MTEyMywNCiAgICAgICAgICAgICAgICAgICAwLjU1NTEyOTIpDQphbm92YShtb2RlbC4xLG1vZGVsLmFsbDEpICAgICAgICAgICAgICAgIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gMSwgIjIiID0gMiwiMyIgPSAzLCI0Ij0gNCwgcm93Lm5hbWVzID0gInAtdmFsb3IiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJ0cmFpbjE6IEwgdnMgQ29tcGxldG8iLCJ0cmFpbjE6IEgyUyArIEwgdnMgQ29tcGxldG8iLCJ0cmFpbjI6IEgyUyArIEwgdnMgQ29tcGxldG8iLCAidHJhaW4xOiBIMlMrIEwgdnMgQ29tcGxldG8iKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX3B2YWxvcmVzDQpkZl9wdmFsX2Ryb3BfcDEgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgDQpgYGANCg0KQ29uIGVzdG9zIHAtdmFsb3JlcyBwb2RlbW9zIGRlY2lyIHF1ZSBjb24gdW4gbml2ZWwgZGUgc2lnbmlmaWNhY2nDs24gJFxhbHBoYSQgbmluZ8O6biBtb2RlbG8gZXMgbm90YWJsZW1lbnRlIGRpZmVyZW50ZSBkZSBzdSBjb250cmFwYXJ0ZSBzYWx2byBlbiBlbCBjYXNvIGRlIGxvcyBtb2RlbG9zIHJlc3VsdGFudGVzIGVuICp0cmFpbjIqIGVzdG8gcHVlZGUgc2VyIHBvciBsYSBjYW50aWRhZCBkZSBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIHByZXNlbnRlcyBlbiBsYSBtdWVzdHJhLCBsbyB0cmF0YXJlbW9zIGVuIGxhIHNpZ3VpZW50ZSBzZWNjacOzbi4gIA0KDQojIERpYWdub3N0aWNvOiBDb21wcm9iYWNpb25lcyBkZSBoaXBvdGVzaXMsIG91dGxpZXJzIHkgb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcw0KDQpFbiBlc3RhIHNlY2Npw7NuIGVzdHVkaWFyZW1vcyBzaSBudWVzdHJvcyBtb2RlbG9zIGN1bXBsZW4gbGFzIGNvbmRpY2lvbmVzDQpuZWNlc2FyaWFzIGRlIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4gIA0KDQpOdWVzdHJvIGVuZm9xdWUgY29uc2lzdGlyw6EgZW4gdW4gYW7DoWxpc2lzIGdyw6FmaWNvLCBhY29tcGHDsWFkbyBkZSB0ZXN0cw0KZXN0YWTDrXN0aWNvcyBlbiBsb3MgY2Fzb3MgZW4gbG9zIHF1ZSBzZSBhcHJlY2llIHVuYSBkaXNjcmVwYW5jaWEgbm90YWJsZS4NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmF0dGFjaChjaGVkZGFyKQ0KYGBgDQoNCiMjIMK/U29uIG51ZXN0cm9zICptb2RlbG9zKiwgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbD86IENvbXByb2JhY2nDs24gZGUgaGlww7N0ZXNpcy4NCg0KRW4gbGEgc2VjY2nDs24gMyBzZSB0b21hIHVuIGVuZm9xdWUgKm5hw692ZSogYSBsYSBob3JhIGRlIGNvbnN0cnVpciBsb3MgbW9kZWxvcywNCnlhIHF1ZSBubyBoZW1vcyBlc3R1ZGlhZG8gc2kgaGF5IG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMsIHBvZHLDrWFtb3MgdGVuZXIgdW5hDQptdWVzdHJhIHF1ZSBubyBlcyBsYSBhZGVjdWFkYSBwYXJhIGVsIGVzdHVkaW8gZGUgbnVlc3Ryb3MgZGF0b3MuICANCg0KVW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIGRlYmUgc2F0aXNmYWNlciBsYXMgc2lndWllbnRlcyBoaXDDs3Rlc2lzIGNvbiBuaXZlbCANCmRlIHNpZ25pZmljYWNpw7NuICRcYWxwaGEkIGFkZWN1YWRvOg0KDQoxLiBMb3MgZXJyb3JlcyBcKFxlcHNpbG9uX3tpfVwpIHRpZW5lbiBkaXN0cmlidWNpw7NuIG5vcm1hbC4gIA0KMi4gTG9zIGVycm9yZXMgXChcZXBzaWxvbl97aX1cKSB0aWVuZW4gbWVkaWEgY2Vyby4gIA0KMy4gTG9zIGVycm9yZXMgXChcZXBzaWxvbl97aX1cKSB0aWVuZW4gdmFyaWFuemEgY29uc3RhbnRlLiAgDQo0LiBMb3MgZXJyb3JlcyBcKFxlcHNpbG9uX3tpfVwpIG5vIGVzdMOhbiBjb3JyZWxhY2lvbmFkb3MuICANCg0KYGBge3IgaW5jbHVkZT1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KYWxmYW4gPC0gMC4wNQ0KZmlsYV9saW5lYWxpZGFkIDwtIGMocm91bmQocmVzZXR0ZXN0KG1vZGVsLjEsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJlc2V0dGVzdChtb2RlbC4xY3JpdCwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQocmVzZXR0ZXN0KG1vZGVsLjIsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjIsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJlc2V0dGVzdChtb2RlbC4zLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4zLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICBhbGZhbiwiUmVzZXR0ZXN0IikNCmZpbGFfbm9ybWFsaWRhZCA8LSBjKHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xKSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdCkpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMikpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMykpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICBhbGZhbiwgIlRlc3QgU2hhcGlybyBXaWxrIikNCmZpbGFfbWVkaWFPIDwtIGModC50ZXN0KHJlc2lkKG1vZGVsLjEpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgIHQudGVzdChyZXNpZChtb2RlbC4xY3JpdCksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgdC50ZXN0KHJlc2lkKG1vZGVsLjIpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgIHQudGVzdChyZXNpZChtb2RlbC4zKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICBhbGZhbiwgInQtdGVzdCIpDQpmaWxhX3Zhcl9jdGUgPC0gYyhyb3VuZChuY3ZUZXN0KG1vZGVsLjEpJHAsMyksDQogICAgICAgICAgICAgICAgICByb3VuZChuY3ZUZXN0KG1vZGVsLjFjcml0KSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4yKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4zKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgYWxmYW4sICJUZXN0IG5jdiIpDQogICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgIA0KZmlsYV9jb3JyIDwtIGMoZHVyYmluV2F0c29uVGVzdChtb2RlbC4xKSRwLA0KICAgICAgICAgICAgICAgZHVyYmluV2F0c29uVGVzdChtb2RlbC4xY3JpdCkkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMikkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMykkcCwNCiAgICAgICAgICAgICAgIGFsZmFuLCJUZXN0IGRlIER1cmJpbi1XYXRzb24iKQ0KIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNSksIjIiID0gcmVwKDAsNSksIjMiID0gcmVwKDAsNSksIjQiPSByZXAoMCw1KSwgIjUiPSByZXAoMCw1KSwgIjYiID0gcmVwKDAsNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9YygiTGluZWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWVkaWEgPSAwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYXJpYW56YSBjb25zdGFudGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGFjacOzbiIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJ0cmFpbjE6IEwiLCJ0cmFpbjE6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjI6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjM6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOaXZlbCBkZSBzaWdpbmlmaWNhY2nDs24iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUZXN0IHV0aWxpemFkbyIpDQoNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9saW5lYWxpZGFkDQpkZl9wdmFsX2Ryb3BfcDFbMixdIDwtIGZpbGFfbm9ybWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBmaWxhX21lZGlhTw0KZGZfcHZhbF9kcm9wX3AxWzQsXSA8LSBmaWxhX3Zhcl9jdGUNCmRmX3B2YWxfZHJvcF9wMVs1LF0gPC0gZmlsYV9jb3JyDQpgYGANCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQoNClBvZGVtb3Mgb2JzZXJ2YXIgcXVlIHNlIHZlcmlmaWNhbiBhIG5pdmVsIGRlIHNpZ25pZmljYWNpw7NuICRcYWxwaGEkID0gMC4wNSBzZSB2ZXJpZmljYW4gdG9kYXMgbGFzIGhpcMOzdGVzaXMgZGUgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsLiBFbiBsYXMgc2lndWllbnRlcyBncsOhZmljYXMgcG9kZW1vcyBvYnNlcnZhciBjb21vIGxvcyByZXNpZHVvcyBkZSBsb3MgbW9kZWxvcyAqKnRhc3RlIH4gSDJTICsgTCoqIGRlIGxvcyBjb25qdW50b3MgKnRyYWluMiogeSAqdHJhaW4zKiBzZSBjb21wb3J0YW4gbWVqb3IgcXVlIGN1YWxxdWllcmEgZGUgbG9zIG1vZGVsb3MgcHJvcHVlc3RvcyBlbiBsYSBtdWVzdHJhICp0cmFpbjEqDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTZ9DQpwYXIobWZyb3c9YygxLDIpKQ0KcXFub3JtKHJlc2lkKG1vZGVsLjEpKQ0KcXFsaW5lKHJlc2lkKG1vZGVsLjEpKQ0KDQpxcW5vcm0ocmVzaWQobW9kZWwuMWNyaXQpKQ0KcXFsaW5lKHJlc2lkKG1vZGVsLjFjcml0KSkNCg0KYGBgDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD02fQ0KcGFyKG1mcm93PWMoMSwyKSkNCnFxbm9ybShyZXNpZChtb2RlbC4yKSkNCnFxbGluZShyZXNpZChtb2RlbC4yKSkNCg0KcXFub3JtKHJlc2lkKG1vZGVsLjMpKQ0KcXFsaW5lKHJlc2lkKG1vZGVsLjMpKQ0KDQpgYGANCg0KDQpQb3N0ZXJpb3JtZW50ZSwgcmVhbGl6YW1vcyB1biBlc3R1ZGlvIGRlIGxhIGNvbGluZWFsaWRhZC4gUGFyYSBlbGxvLCBvYnNlcnZhbW9zIHF1ZSBlbCBtb2RlbG8gKip0YXN0ZSB+IExhY3RpYyAsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0qKiBzb2xvIHRpZW5lIHVuIHByZWRpY3RvciBsdWVnbyBubyBoYXkgcHJlc2VudGUgbmluZ8O6biB0aXBvIGNvbGluZWFsaWRhZC4NCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KIyB2aWYobW9kZWwuMSkgZGlqaW1vcyBxdWUgZWwgZGUgbGFjdGljIG5vIHBvcnF1ZSBzdWNlZGUgZXN0byBubyBoYXkgY29saW4gcG9yIHNvbG8gMSB2YXINCiMgdmlmKG1vZGVsLjFjcml0KQ0KIyB2aWYobW9kZWwuMikNCiMgdmlmKG1vZGVsLjMpICMgbG9zIHZhbG9yZXMgZGUgVklGIG5vIGluZGljYW4gY29saW5lYWxpZGFkIGdyYXZlDQoNCg0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNCksIjIiID0gcmVwKDAsNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPWMoInRyYWluMTogTCIsInRyYWluMTogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMjogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMzogSDJTICsgTCIpKQ0KDQpmaWxhX2MxIDwtIGMoIlNvbG8gdGllbmUgdW4gcHJlZGljdG9yIiwiU29sbyB0aWVuZSB1biBwcmVkaWN0b3IiKQ0KZmlsYV9jMiA8LSBjKHZpZihtb2RlbC4xY3JpdClbWzFdXSx2aWYobW9kZWwuMWNyaXQpW1syXV0pDQpmaWxhX2MzIDwtIGModmlmKG1vZGVsLjIpW1sxXV0sdmlmKG1vZGVsLjIpW1syXV0pDQpmaWxhX2M0IDwtIGModmlmKG1vZGVsLjMpW1sxXV0sdmlmKG1vZGVsLjMpW1syXV0pDQoNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9jMQ0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX2MyDQpkZl9wdmFsX2Ryb3BfcDFbMyxdIDwtIGZpbGFfYzMNCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV9jNA0KDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtIGMoIkgyUyIsIkxhY3RpYyIpDQpkZl9wdmFsX2Ryb3BfcDENCg0KYGBgDQoNCk51ZXN0cm9zIHZhbG9yZXMgc29uIG11eSBidWVub3MsIGVudGVuZGllbmRvIHBvciBidWVubyBWSUYgPCAxMCwgcG9yIGxvIHRhbnRvIG5vIHRlbmVuZW1vcyBxdWUgcHJlb2N1cGFybm9zIGRlIHVuYSBjb2xpbmVhbGlkYWQgZ3JhdmUgZW50cmUgbGFzIHZhcmlhYmxlcy4NCg0KDQojIyBFc3R1ZGlvIGRlIG91dGxpZXJzDQoNCkEgZmluIGRlIG9idGVuZXIgZGlzdGludG9zIHB1bnRvcyBkZSB2aXN0YSB1dGlsaXphcmVtb3MgZG9zIG3DqXRvZG9zLCB1biB2YWxvciBkZSBCb25mZXJyb25pIGVuIHVuIGVzdGFkw61zdGljbyAkdF97MS1cZnJhY3tcYWxwaGF9ezJufTtuLXAtMX0kIHkgbGEgZnVuY2nDs24gKm91dGxpZXJUZXN0KiBxdWUgdXRpbGl6YSBwLXZhbG9yZXMgZGUgQm9uZmVycm9uaSBvYnRlbmlkb3MgYSB0cmF2w6lzIGRlIHQtdGVzdHMuICANCg0KRW4gbG9zIGN1YXRybyBtb2RlbG9zIHkgYmFqbyBsb3MgZG9zIGNyaXRlcmlvcyBubyBzZSBvYnRpZW5lIG5pbmd1bmEgb2JzZXJ2YWNpw7NuIHF1ZSBzZSBwdWVkYSBhY2VwdGFyIGNvbW8gKm91dGxpZXIqIGEgbml2ZWwgZGUgc2lnbmlmaWNhY2nDs24gJFxhbHBoYSQgPSAwLjA1DQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpzaWduaSA8LSAwLjA1DQoNCm4xPC1ucm93KGNoZWRkYXJbdHJhaW4uMSxdKQ0KcDEgPC1ucm93KHN1bW1hcnkobW9kZWwuMSkkY29lZikNCg0KDQpuMWNyaXQ8LW5yb3coY2hlZGRhclt0cmFpbi4xLF0pDQpwMWNyaXQgPC1ucm93KHN1bW1hcnkobW9kZWwuMWNyaXQpJGNvZWYpDQoNCm4yPC1ucm93KGNoZWRkYXJbdHJhaW4uMixdKQ0KcDIgPC1ucm93KHN1bW1hcnkobW9kZWwuMikkY29lZikNCg0KbjM8LW5yb3coY2hlZGRhclt0cmFpbi4zLF0pDQpwMyA8LW5yb3coc3VtbWFyeShtb2RlbC4zKSRjb2VmKQ0KDQpCQ1YxIDwtIHF0KDEgLSBzaWduaSAvICgyICogbjEpLCBuMS1wMS0xKSANCkJDVjFjcml0IDwtIHF0KDEgLSBzaWduaSAvICgyICogbjFjcml0KSwgbjFjcml0LXAxY3JpdC0xKSANCkJDVjIgPC0gcXQoMSAtIHNpZ25pIC8gKDIgKiBuMiksIG4yLXAyLTEpIA0KQkNWMyA8LSBxdCgxIC0gc2lnbmkgLyAoMiAqIG4zKSwgbjMtcDMtMSkgDQoNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMSkpID4gQkNWMSkNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMWNyaXQpKSA+IEJDVjFjcml0KQ0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4yKSkgPiBCQ1YyKQ0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4zKSkgPiBCQ1YzKQ0KDQoNCm91dGxpZXJUZXN0KG1vZGVsLjEpDQpvdXRsaWVyVGVzdChtb2RlbC4xY3JpdCkjTkE/DQpvdXRsaWVyVGVzdChtb2RlbC4yKSAjIG5vIGhheSBlbiBuaW5ndW5vIGRlIGxvcyBkb3MgbW9kZWxvcyBwbGFudGVhZG9zDQpvdXRsaWVyVGVzdChtb2RlbC4zKQ0KDQpgYGANCiMjIEVzdHVkaW8gZGUgb2JzZXJ2YWNpb25lcyBJbmZsdXllbnRlcw0KDQpBbCBpZ3VhbCBxdWUgZW4gbGEgYW50ZXJpb3Igc2VjY2nDs24gYSBmaW4gZGUgcG9kZXIgZW5jb250cmFyIGVsIGNyaXRlcmlvIHF1ZSBtZWpvciBzZSBhanVzdGUgYSBudWVzdHJvIG1vZGVsbywgZW4gZWwgcXVlIGhheSBxdWUgdGVuZXIgZW4gY3VlbnRhIHF1ZSBlcyB1bmEgbXVlc3RyYSBkZSB0YW1hw7FvIHJlZHVjaWRvLCB1dGlsaXphcmVtb3MgdmFyaW9zIGNyaXRlcmlvcywgYWRlbcOhcyBkZSBkaXN0aW50YXMgdMOpY25pY2FzIGdyw6FmaWNhcy4gTG9zIGNyaXRlcmlvcyB1c2Fkb3Mgc2Vyw6FuOiAgDQoxLkNyaXRlcmlvIDE6IHZhbG9yZXMgbGV2ZXJhZ2UgKGhpaSkgbWF5b3JlcyBxdWUgJFxmcmFjezJwfXtufSQuICANCjIuQ3JpdGVyaW8gMjogdmFsb3JlcyB8REZGSVRTfCBzb24gbWF5b3JlcyBxdWUgJDIgXGNkb3QgXHNxcnR7XGZyYWN7MnB9e259fSQuICANCg0KMy5Dcml0ZXJpbyAzOiB2YWxvcmVzIHxERkJFVEFTfCBtYXlvcmVzIHF1ZSAkMiBcY2RvdCBcc3FydHtcZnJhY3sycH17bn19JC4gIA0KDQo0LkNyaXRlcmlvIDQ6ICpJbmZsdWVuY2VQbG90Ki4NCg0KRW4gbGEgc2lndWllbnRlIHRhYmxhIG9ic2VydmFtb3MgbGFzIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMgb2J0ZW5pZGFzIHBvciBjYWRhIGNyaXRlcmlvLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQoNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDQpLCIyIiA9IHJlcCgwLDQpLCIzIiA9IHJlcCgwLDQpLCI0IiA9IHJlcCgwLDQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID1jKCJ0cmFpbjE6IEwiLCJ0cmFpbjE6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjI6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjM6IEgyUyArIEwiKSkNCg0KZmlsYV9jMSA8LSBjKCIxLDUsMTYsMjMsMjQsMjYiLCAiMSwxMiwyNCIsIjEsMyw1LDgsOSwxMiwxMywxNCwxNiwxOSwyMywyNCwyNywyOCwzMCIsIjEsMTIsMjQiKQ0KZmlsYV9jMiA8LSBjKCIyMyIsICIxMiIsICIxLDMsOCw5LDExLDEyLDEzLDE0LDE5LDIzLDI0LDI2LDI3LDI4LDMwIiwiMSw4LDEyLDIzIikNCmZpbGFfYzMgPC0gYygiNiIsIk5pbmd1bm8iICwgIjEsMyw0LDcsOCw5LDExLDEyLDE2LDE3LDIwLDI5LDMwIiwiMSw2LDcsOCwxNSIpDQpmaWxhX2M0IDwtIGMoIk5pbmd1bm8iLCJOaW5ndW5vIiwiMSw0LDUsNywxMiwxNCwxNiwxNywxOSwyMywyNywyOSIsIjEsNywxNSwxOSwyNCIpDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtIGMoIkNyaXRlcmlvIDEiLCJDcml0ZXJpbyAyIiwiQ3JpdGVyaW8gMyIsIkNyaXRlcmlvIDQiKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfYzENCmRmX3B2YWxfZHJvcF9wMVsyLF0gPC0gZmlsYV9jMg0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBmaWxhX2MzDQpkZl9wdmFsX2Ryb3BfcDFbNCxdIDwtIGZpbGFfYzQNCmRmX3B2YWxfZHJvcF9wMQ0KYGBgDQoNClRvbWFtb3MgbGEgZGVjaXNpw7NuIGRlIGVsZWdpciBsb3MgZWxlbWVudG9zIHF1ZSBzZSByZXBpdGFuIGVuIHZhcmlvcyB5YSBxdWUgc2kgZWxpbWluw6FzZW1vcyBsb3MgZGVsIGNyaXRlcmlvIDMgZWwgcmVzdWx0YWRvIHNlcsOtYSBkZW1hc2lhZG8gcGVxdWXDsW8gcGFyYSBzZXIgYXB0byBwYXJhIGxhIHJlZ3Jlc2nDs24gbGluZWFsLiBOdWVzdHJvIGNyaXRlcmlvIGEgc2VndWlyIGVzIHF1ZSBlc3TDqW4gZW4gYWwgbWVub3MgZG9zIGNyaXRlcmlvcyAgZGUgbG9zIHJlc3RhbnRlcy4NCg0KYGBge3IgZWNobz1GQUxTRX0NCg0KcGFyKG1mcm93PWMoMiwyKSkNCnAxIDwtIGluZmx1ZW5jZVBsb3QobW9kZWwuMSkNCnBvc19pbmZsdXllbnRlc18xIDwtIGMoMSwxMiwyNCkNCg0KcDIgPC1pbmZsdWVuY2VQbG90KG1vZGVsLjFjcml0KQ0KcG9zX2luZmx1eWVudGVzXzFjcml0IDwtIGMoMSw4LDEyLDIzKQ0KDQpwMyA8LWluZmx1ZW5jZVBsb3QobW9kZWwuMikNCnBvc19pbmZsdXllbnRlc18yIDwtIGMoMSw2LDcsOCwxNSkNCg0KDQpwNCA8LWluZmx1ZW5jZVBsb3QobW9kZWwuMykNCnBvc19pbmZsdXllbnRlc18zIDwtIGMoMSw3LDE1LDE5LDI0KQ0KDQpgYGANCg0KRXN0YXMgb2JzZXJ2YWNpb25lcyBzb24gbGFzIHByZXNlbnRlcyBlbiBsYSBjdWFydGEgY29sdW1uYSBkZSBsYSB0YWJsYSB5IGVuIGdlbmVyYWwgc29uIGVuIGxhcyBwcmltZXJhcyBlbiBsYXMgcXVlIG5vcyBmaWplbW9zIGEgbGEgaG9yYSBkZSB2ZXIgc2kgbGFzIHRvbWFtb3MgY29tbyBpbmZsdXllbnRlcyBvIG5vLg0KDQpCYWpvIG51ZXN0cm8gY3JpdGVyaW8gcXVlZGFyw61hbiBjb21vIHBvc2libGVzIGluZmx1eWVudGVzIGxhcyBzaWd1aWVudGVzIG9ic2VydmFjaW9uZXM6DQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9cmVwKDAsNCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPWMoInRyYWluMTogTCIsInRyYWluMTogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMjogSDJTICsgTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRyYWluMzogSDJTICsgTCIpKQ0KDQpmaWxhX2MxIDwtIGMoIjEsMTIiKQ0KZmlsYV9jMiA8LSBjKCIxLDEyLDIzIikNCmZpbGFfYzMgPC0gYygiMiw2IikNCmZpbGFfYzQgPC0gYygiTm8gc2UgcmVwaXRlIG5pbmd1bm8iKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJPYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIikNCg0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX2MxDQpkZl9wdmFsX2Ryb3BfcDFbMixdIDwtIGZpbGFfYzINCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9jMw0KZGZfcHZhbF9kcm9wX3AxWzQsXSA8LSBmaWxhX2M0DQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQoNCkFob3JhIGVzIGN1YW5kbyB0ZW5lbW9zIHF1ZSBkZXRlcm1pbmFyIHNpIHZhbiBhIHNlciBpbmZsdXllbnRlcyBvIG5vLCBlc3RvIGxvIHZlcmVtb3MgY29tcGFyYW5kbyBsb3MgbW9kZWxvcyBjb24gbGFzIG11ZXN0cmFzIGRlIGVudHJlbmFtaWVudG8gc2luIGVsaW1pbmFyIGluZmx1eWVudGVzIHkgY29uIGxhcyBtdWVzdHJhcyBtb2RpZmljYWRhcywgeSBldmFsdWFyIHNpIG1lam9yYW4gbyBlbXBlb3JhbiBsb3MgcC12YWxvcmVzIGRlIGxhcyBoaXDDs3Rlc2lzIGRlIGxvcyBtb2RlbG9zIGRlIHJlZ3Jlc2nDs24uDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpwb3NfMTwtYyhUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsMTgpKQ0KdHJhaW4uMWluZjwtdHJhaW4uMSYhcG9zXzENCm1vZGVsLjFpbmY8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWluZixdKQ0KYGBgDQojIyMgdGFzdGUgfiAgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSB2cyB0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWluZixdDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQoNCmZpbGFfbGluZWFsaWRhZCA8LSBjKHJvdW5kKHJlc2V0dGVzdChtb2RlbC4xLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChyZXNldHRlc3QobW9kZWwuMWluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMWluZixdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgIlJlc2V0dGVzdCIpDQoNCg0KZmlsYV9ub3JtYWxpZGFkIDwtIGMocm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjEpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjFjcml0KSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgICJUZXN0IFNoYXBpcm8gV2lsayIpDQpmaWxhX21lZGlhTyA8LSBjKHQudGVzdChyZXNpZChtb2RlbC4xKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICB0LnRlc3QocmVzaWQobW9kZWwuMWluZiksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgInQtdGVzdCIpDQpmaWxhX3Zhcl9jdGUgPC0gYyhyb3VuZChuY3ZUZXN0KG1vZGVsLjEpJHAsMyksDQogICAgICAgICAgICAgICAgICByb3VuZChuY3ZUZXN0KG1vZGVsLjFpbmYpJHAsMyksDQogICAgICAgICAgICAgICAgICAiVGVzdCBuY3YiKQ0KICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICANCmZpbGFfY29yciA8LSBjKGR1cmJpbldhdHNvblRlc3QobW9kZWwuMSkkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMWluZikkcCwNCiAgICAgICAgICAgICAgICJUZXN0IGRlIER1cmJpbi1XYXRzb24iKQ0KIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNSksIjIiID0gcmVwKDAsNSksIjMiID0gcmVwKDAsNSkscm93Lm5hbWVzID1jKCJMaW5lYWxpZGFkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhID0gMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhcmlhbnphIGNvbnN0YW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGFjacOzbiIpKQ0KDQoNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygidHJhaW4xOiBMIiwidHJhaW4xOiBMLCBzaW4gaW5mbHV5ZW50ZXMiLCAiVGVzdCB1dGlsaXphZG8iKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfbGluZWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX25vcm1hbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9tZWRpYU8NCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV92YXJfY3RlDQpkZl9wdmFsX2Ryb3BfcDFbNSxdIDwtIGZpbGFfY29ycg0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCk51ZXN0cmFzIGhpcMOzdGVzaXMgZGVsIG1vZGVsbyBsaW5lYWwgc2UgdmVuIG5vdGFibGVtZW50ZSBtZWpvcmFkYXMsIHRlbmVtb3MgdW5hIGRpc3RyaWJ1Y2nDs24gbcOhcyBwYXJlY2lkYSBhIHVuYSBub3JtYWwsIG1lam9yIGRpc3RyaWJ1aWRhIGVuIHRvcm5vIGEgdW5hIGxpbmVhbC4gIA0KUmVhbGl6YW1vcyB1biBwZXF1ZcOxbyBpbnRlcmNhbWJpbyBlbiBlbCBxdWUgbnVlc3RyYSB2YXJpYW56YSBwYXJlY2UgbWVub3MgY29uc3RhbnRlIHBlcm8gc2UgbWFudGllbmUgcG9yIGVuY2ltYSBkZSB0b2RvcyBsb3Mgbml2ZWxlcyBkZSBzaWduaWZpY2FjacOzbiBoYWJpdHVhbGVzLiAgDQpUb21hbW9zIGxhIGRlY2lzacOzbiBkZSBhY3R1YWxpemFyICpjaGVkZGFyW3RyYWluLjEsXSogY29uICAqY2hlZGRhclt0cmFpbmluZi4xLF0qLCBxdWUgZXMgbGEgdmVyc2nDs24gc2luIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMuDQojIyMgdGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSB2cyB0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWNyaXRpbmYsXQ0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnRyYWluLjFhdXg8LXRyYWluLjENCnRyYWluLjE8LXRyYWluLjFpbmYNCm1vZGVsLjE8LW1vZGVsLjFpbmYNCmBgYA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KcG9zXzFjcml0PC1jKFRSVUUscmVwKEZBTFNFLDEwKSxUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsNykpDQoNCnRyYWluLjFjcml0aW5mPC10cmFpbi4xYXV4JiFwb3NfMWNyaXQNCm1vZGVsLjFjcml0aW5mPC0gbG0odGFzdGUgfkgyUytMYWN0aWMgLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xY3JpdGluZixdKQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCg0KZmlsYV9saW5lYWxpZGFkIDwtIGMocm91bmQocmVzZXR0ZXN0KG1vZGVsLjFjcml0LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChyZXNldHRlc3QobW9kZWwuMWNyaXRpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjFjcml0aW5mLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiUmVzZXR0ZXN0IikNCg0KDQpmaWxhX25vcm1hbGlkYWQgPC0gYyhyb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMWNyaXQpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjFjcml0aW5mKSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgICJUZXN0IFNoYXBpcm8gV2lsayIpDQpmaWxhX21lZGlhTyA8LSBjKHQudGVzdChyZXNpZChtb2RlbC4xY3JpdCksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgdC50ZXN0KHJlc2lkKG1vZGVsLjFjcml0aW5mKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICAidC10ZXN0IikNCmZpbGFfdmFyX2N0ZSA8LSBjKHJvdW5kKG5jdlRlc3QobW9kZWwuMWNyaXQpJHAsMyksDQogICAgICAgICAgICAgICAgICByb3VuZChuY3ZUZXN0KG1vZGVsLjFjcml0aW5mKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgIlRlc3QgbmN2IikNCiAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgDQpmaWxhX2NvcnIgPC0gYyhkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjFjcml0KSRwLA0KICAgICAgICAgICAgICAgZHVyYmluV2F0c29uVGVzdChtb2RlbC4xY3JpdGluZikkcCwNCiAgICAgICAgICAgICAgICJUZXN0IGRlIER1cmJpbi1XYXRzb24iKQ0KIA0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsNSksIjIiID0gcmVwKDAsNSksIjMiID0gcmVwKDAsNSkscm93Lm5hbWVzID1jKCJMaW5lYWxpZGFkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhID0gMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlZhcmlhbnphIGNvbnN0YW50ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGFjacOzbiIpKQ0KDQoNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygidHJhaW4xOiBIMlMgKyBMIiwidHJhaW4xOiBIMlMgKyBMLCBzaW4gaW5mbHV5ZW50ZXMiLCAiVGVzdCB1dGlsaXphZG8iKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfbGluZWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX25vcm1hbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9tZWRpYU8NCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV92YXJfY3RlDQpkZl9wdmFsX2Ryb3BfcDFbNSxdIDwtIGZpbGFfY29ycg0KDQoNCg0KDQpkZl9wdmFsX2Ryb3BfcDENCg0KDQpgYGANCkVzdGUgZXMgdW4gY2FzbyB1biB0YW50byBwYXJ0aWN1bGFyLCB0ZW5lbW9zIHVub3MgZGF0b3MgcGVyZmVjdGFtZW50ZSBkaXN0cmlidWlkb3MsIHBlcm8geWEgbG8gZXN0YWJhbiBhbnRlcyBwcmFjdGljYW1lbnRlLiBBIGNhbWJpbyBkZSBlc28gcGVyZGVtb3MgdW4gY2llcnRvIGdyYWRvIGRlIGxpbmVhbGlkYWQgcXVlIGhheSBxdWUgdGVuZXIgZW4gY3VlbnRhLCBlbiBlc3RlIGNhc28gbm8gaGF5IHVuYSBkaWZlcmVuY2lhIHRhbiBub3RhYmxlIGNvbiBlbCBtb2RlbG8gY29tbyBlbiBxdWUgc29sbyBpbmNvcnBvcmFiYSBhIExhY3RpYy4gIA0KDQpUb21hbW9zIGxhIGRlY2lzacOzbiBkZSBhY3R1YWxpemFyICpjaGVkZGFyW3RyYWluLjFjcml0LF0qIGNvbiAgKmNoZWRkYXJbdHJhaW4uMWNyaXRpbmYsXSosIHF1ZSBlcyBsYSB2ZXJzacOzbiBzaW4gb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcy4NCg0KIyMjIHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0gdnMgdGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjJpbmYsXQ0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnRyYWluLjFjcml0PC10cmFpbi4xY3JpdGluZg0KbW9kZWwuMWNyaXQ8LSBtb2RlbC4xY3JpdGluZg0KYGBgDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnBvc18yPC1jKHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSwyNCkpDQoNCnRyYWluLjJpbmY8LXRyYWluLjImIXBvc18yDQptb2RlbC4yaW5mPC0gbG0odGFzdGUgfiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaW5mLF0pDQpgYGANCg0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCg0KZmlsYV9saW5lYWxpZGFkIDwtIGMocm91bmQocmVzZXR0ZXN0KG1vZGVsLjIsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjIsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJlc2V0dGVzdChtb2RlbC4yaW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yaW5mLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiUmVzZXR0ZXN0IikNCg0KDQpmaWxhX25vcm1hbGlkYWQgPC0gYyhyb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMikpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMmluZikpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiVGVzdCBTaGFwaXJvIFdpbGsiKQ0KZmlsYV9tZWRpYU8gPC0gYyh0LnRlc3QocmVzaWQobW9kZWwuMiksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgdC50ZXN0KHJlc2lkKG1vZGVsLjJpbmYpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgICJ0LXRlc3QiKQ0KZmlsYV92YXJfY3RlIDwtIGMocm91bmQobmN2VGVzdChtb2RlbC4yKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4yaW5mKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgIlRlc3QgbmN2IikNCiAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgDQpmaWxhX2NvcnIgPC0gYyhkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjIpJHAsDQogICAgICAgICAgICAgICBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjJpbmYpJHAsDQogICAgICAgICAgICAgICAiVGVzdCBkZSBEdXJiaW4tV2F0c29uIikNCiANCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDUpLCIyIiA9IHJlcCgwLDUpLCIzIiA9IHJlcCgwLDUpLHJvdy5uYW1lcyA9YygiTGluZWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGlkYWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWRpYSA9IDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYXJpYW56YSBjb25zdGFudGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb3JyZWxhY2nDs24iKSkNCg0KDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtICAgIGMoInRyYWluMjogSDJTICsgTCIsInRyYWluMjogSDJTICsgTCwgc2luIGluZmx1eWVudGVzIiwgIlRlc3QgdXRpbGl6YWRvIikNCg0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX2xpbmVhbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVsyLF0gPC0gZmlsYV9ub3JtYWxpZGFkDQpkZl9wdmFsX2Ryb3BfcDFbMyxdIDwtIGZpbGFfbWVkaWFPDQpkZl9wdmFsX2Ryb3BfcDFbNCxdIDwtIGZpbGFfdmFyX2N0ZQ0KZGZfcHZhbF9kcm9wX3AxWzUsXSA8LSBmaWxhX2NvcnINCg0KDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KRW4gY2llcnRhIG1hbmVyYSBlcyBub3RhYmxlIHF1ZSBhbCBlbGltaW5hciBudWVzdHJhcyBpbmZsdXllbnRlcyB5IGVuIHVuICpkYXRhc2V0KiB0YW4gcGVxdWXDsW8gbm8gZ2VuZXJlIGEgcGVuYXMgZGlmZXJlbmNpYSwgZW4gdG9kbyBjYXNvIG5vcyBtZWpvcmEgdG9kYXMgbGFzIGhpcMOzdGVzaXMgZGVsIG1vZGVsbyBsaW5lYWwsIHNlIHB1ZWRlIGFmaXJtYXIgcXVlIGVzIHVuIG1vZGVsbyBtZWpvciBwYXJhIHRyYWJhamFyIHNvYnJlIGVsIGEgcHJpb3JpLiAgDQoNClRvbWFtb3MgbGEgZGVjaXNpw7NuIGRlIGFjdHVhbGl6YXIgKmNoZWRkYXJbdHJhaW4uMixdKiBjb24gICpjaGVkZGFyW3RyYWluaW5mLjIsXSosIHF1ZSBlcyBsYSB2ZXJzacOzbiBzaW4gb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcy4NCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp0cmFpbi4yPC10cmFpbi4yaW5mDQptb2RlbC4yPC1tb2RlbC4yaW5mDQpgYGANCiMjIyB0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMyxdICANCkVuIGVzdGUgbW9kZWxvLCBiYWpvIGVsIGNyaXRlcmlvIGRlIGVsZWNjacOzbiBkZSBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIHF1ZSBlbGVnaW1vcyBwYXJhIHRyYXRhciBudWVzdHJvcyBkYXRvcywgZXN0ZSBtb2RlbG8gbm8gcHJlc2VudGFiYSBuaW5ndW5hIG9ic2VydmFjacOzbiBpbmZsdXllbnRlLCBwb3IgbG8gcXVlIHNlIG1hbnRpZW5lIGNvbW8gZXN0w6EuDQoNCg0KIyBFcnJvcmVzIGRlIFRlc3QuIENvbXBhcmFjaW9uIGRlIE1vZGVsb3MNCg0KDQoNCk51ZXN0cm8gcmF6b25hbWllbnRvIHBhcmEgZW5mcmVudGFybm9zIGEgZXN0YSBzZWNjacOzbiBlcyBlbCBzaWd1aWVudGUsIG5vcyBoYW4gc2FsaWRvIGRvcyBtb2RlbG9zIHBvc2libGVzIHkgcGFyYSBjb21wcmVuZGVyIGN1YWwgc2UgYWp1c3RhIG1lam9yIGEgbnVlc3Ryb3MgZGF0b3MgdmFtb3MgYSBlc2NvZ2VyIGNpbmNvIHNlZWRzIHkgZXZhbHVhciBjYWRhIG1vZGVsbyBlbiB0b2RhcyBlbGxhcywgYSBmaW4gZGUgaGFjZXIgdW5hIG1lZGlhIGRlIGxvcyBlcnJvcmVzLg0KDQpQYXJhIGVzdG8gdXNhbW9zIGxhcyB0cmVzIHNlZWRzIHF1ZSBoZW1vcyB1dGlsaXphZG8gYSBsbyBsYXJnbyBkZWwgZG9jdW1lbnRvLCB5IGxlIGHDsWFkaW1vcyBvdHJhcyBkb3MgZWxlZ2lkYXMgYWwgYXphci4gTsOzdGVzZSBxdWUgZXZhbHVhciBlbiBsYSBwcmltZXJhIHNlZWQgeWEgZXN0w6EgaGVjaG8sIHB1ZXMgZW4gZXN0YSBub3Mgc2Fsw61hbiBsb3MgZG9zIG1vZGVsb3MgYSBjb25zaWRlcmFyLiBBZGVtw6FzIGVuIGxhcyBzZWVkcyBkb3MgeSB0cmVzIHlhIGVzdMOhIGhlY2hvIHBhcmEgZWwgbW9kZWxvIGNvbiBIMlMgKyBMYWN0aWMsIHBlcm8gaGF5IHF1ZSByZXBldGlyIGVsIHByb2Nlc28gcGFyYSBlbCBvdHJvIG1vZGVsby4NCkRlIGVzdGEgbWFuZXJhIHJlYWxpemFtb3MgbG9zIG1pc21vcyBjw6FsY3Vsb3MgcXVlIGxvcyByZWFsaXphZG9zIGVuIGxhIHBhcnRlIGRlIGRpYWduw7NzdGljbywgc29icmUgbGFzIGNvbWJpbmFjaW9uZXMuIEVzdG8gZXMsIG5vcyBhc2VndXJhbW9zIHF1ZSBjYWRhIG1vZGVsbyBjb24gdG9kb3MgbG9zIHRyYWluIGN1bXBsYSBsYXMgaGlww7N0ZXNpcyBkZSBub3JtYWxpZGFkLCBtZWRpYSBkZSBlcnJvcmVzIG51bGEsIGhvbW9jZWRhc3RpY2lkYWQsIGxpbmVhbGlkYWQgeSBhdXRvY29ycmVsYWNpw7NuLiBEZXNwdcOpcyBkZSBlc3RvIG5vcyBwbGFudGVhbW9zIHNpIHRpZW5lIGRhdG9zIGluZmx1eWVudGVzIHNlZ8O6biBsYXMgZnVuY2lvbmVzIGFkZWN1YWRhcywgZW4gY2FzbyBkZSB0ZW5lcmxvcyByZWFsaXphbW9zIHVuYSBwcnVlYmEuIGxvcyBxdWl0YW1vcyBkZWwgdHJhaW4geSB2ZW1vcyBzaSBzZSBtZWpvcmEgZWwgcC12YWxvciBkZSBhbGd1bmEgZGUgbGFzIGNhcmFjdGVyw61zdGljYXMgYW50ZXJpb3JlcyB5IGVuIGJhc2UgYSBlc28gZGVjaWRpbW9zIHNpIGVsaW1pbmFtb3MgbGFzIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMgbyBuby4gDQoNCkNvbiB0b2RvIGVzbyByZWFsaXphZG8gbGxlZ2Ftb3MgYSBsYSBzaWd1aWVudGUgdGFibGEsIHF1ZSBub3MgcGVybWl0ZSBhc3VtaXIgY29tbyB2YWxpZG9zIHRvZG9zIGxvcyBjYXNvcyB5IGNhbGN1bGFyIHN1cyBlcnJvcmVzLg0KDQoNCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgSU5UUk9EVUNJUiBTRUNDSU9OIDUNCiMgQ09NUExFVEFSIFRBQkxBIE9VVExJRVJTDQojIENSRU8gUVVFIFRFTklBIFFVRSBQT05FUiBIT01PRVNUIEFSUklCQQ0KIyBKVVNUTyBFTiBFTCBTVU1NQVJZIERFIExBIFNFQ0NJT04gNiBDUkVPIFFVRSBFTCBEQVRBIE5PIERFQkVSSUEgU0VSIENIRUREQVINCg0KIyBWYW1vcyBhIGNvbnNpZGVyYXIgb3RyYXMgZG9zIHNlbWlsbGFzIHBhcmEgZXZhbHVhciBsb3MgbW9kZWxvcyB5IGVsZWdpciBlbCBtZWpvci4NCiMgTGFzIHRvbWFtb3MgZGUgZm9ybWEgcXVlIG5vIGNvaW5jaWRhbiBlbiBsYSBtZWRpZGEgZGUgbG8gcG9zaWJsZSBsb3MgdGVzdHMgZGUgbGFzIGRpc3RpbnRhcyBwYXJ0aWNpb25lcy4NCiMgRGl2aWRpbW9zIGVsIGNvbmp1bnRvIHRvdGFsIHBhcmEgbGFzIGRvcyBzZW1pbGxhcyBudWV2YXMuDQoNCnNldC5zZWVkKCgyMjM0KSkNCnRyYWluLjQgPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBzaXplID0gbnJvdyhjaGVkZGFyKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCnRlc3QuNCA8LSAoIXRyYWluLjQpDQpzdW0odGVzdC40KQ0Kc3VtKHRlc3QuMT09VFJVRSAmIHRlc3QuND09VFJVRSkNCnN1bSh0ZXN0LjI9PVRSVUUgJiB0ZXN0LjQ9PVRSVUUpDQpzdW0odGVzdC4zPT1UUlVFICYgdGVzdC40PT1UUlVFKQ0KDQoNCnNldC5zZWVkKCgxMzEpKQ0KdHJhaW4uNSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC41IDwtICghdHJhaW4uNSkNCnN1bSh0ZXN0LjUpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC41PT1UUlVFKQ0Kc3VtKHRlc3QuMj09VFJVRSAmIHRlc3QuNT09VFJVRSkNCnN1bSh0ZXN0LjM9PVRSVUUgJiB0ZXN0LjU9PVRSVUUpDQpzdW0odGVzdC40PT1UUlVFICYgdGVzdC41PT1UUlVFKQ0KDQp0cmFpbi4xaCA8LSB0cmFpbi4xY3JpdA0KdHJhaW4uMmggPC0gdHJhaW4uMg0KdHJhaW4uM2ggPC0gdHJhaW4uMw0KdHJhaW4uNGggPC0gdHJhaW4uNA0KdHJhaW4uNWggPC0gdHJhaW4uNQ0KDQojIFJlY2FsY3VsYW1vcyB0cmFpbi4yIHBvcnF1ZSBmdWUgbW9kaWZpY2Fkbw0Kc2V0LnNlZWQoMTEwMCkNCnRyYWluLjIgPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBzaXplID0gbnJvdyhjaGVkZGFyKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCg0KDQoNCg0KIyBWZWFtc28gc2kgcG9kZW1vcyBlbGltaW5hciBwb3NpYmxlcyBpbmZsdXllbnRlcyBlbiBsb3MgbW9kZWxvcyByZXN0YW50ZXMNCg0KbWgxIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xaCxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbWgyIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaCxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbWgzIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zaCxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbWg0IDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40aCxdKQ0KbWg1IDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi41aCxdKQ0KDQptMSA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKSAjIGNvbXByb2JhZG9zIHN1cHVlc3Rvcw0KbTIgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjIsXSkNCm0zIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0pDQptNCA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNCxdKQ0KbTUgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjUsXSkNCg0KDQojIEFsIGlndWFsIHF1ZSBoaWNpbW9zIGVuIDQgY29tcHJvYmFtb3Mgc2kgcmV0aXJhbmRvIG91dGxpZXJzIHkgb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcyBtZWpvcmFuIGxhcyBoaXBvdGVzaXMuDQojICBVbmljYW1lbnRlIGNvbnNpZGVyYXJlbW9zIG9ic2VydmFjaW9uZXMgb2J0ZW5pZGFzIHRhbnRvIHBvciBvdXRsaWVyVGVzdCgpIGNvbW8gcG9yIGluZmx1ZW5jZVBsb3QoKS4NCg0KIyBtaDQNCm91dGxpZXJUZXN0KG1oNCkNCmluZmx1ZW5jZVBsb3QobWg0KSAjIDYsMTIsMTUsMjQNCnBvczRoIDwtIGMocmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDgpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi40aW5mIDwtIHRyYWluLjRoJiFwb3M0aA0KbWg0aW5mIDwtIGxtKHRhc3RlIH4gSDJTK0xhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNGluZixdKQ0KDQpuY3ZUZXN0KG1oNCkNCm5jdlRlc3QobWg0aW5mKSAjIG1lam9yYSBNVUNITw0KDQpzaGFwaXJvLnRlc3QocmVzaWQobWg0KSkNCnNoYXBpcm8udGVzdChyZXNpZChtaDRpbmYpKSAjIG1lam9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG1oNCkNCmR1cmJpbldhdHNvblRlc3QobWg0aW5mKSAjIG1lam9yYQ0KDQpyZXNldHRlc3QobWg0LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pIA0KcmVzZXR0ZXN0KG1oNGluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNGluZixdKSAjIGVtcGVvcmEgcGVybyBlcyBhY2VwdGFibGUNCg0KIyBSZWRlZmluaW1vcyBlbGltaW5hbmRvIHBvczRoIHBvciBzZXIgdGFudGEgbGEgbWVqb3JhIGVuIGhvbW9jZWRhc3RpY2lkYWQgcXVlIGNvbXBlbnNhIGxhIGxpbmVhbGlkYWQNCnRyYWluLjRoIDwtIHRyYWluLjRpbmYNCm1oNCA8LSBtaDRpbmYNCg0KDQojIG1oNQ0Kb3V0bGllclRlc3QobWg1KQ0KaW5mbHVlbmNlUGxvdChtaDUpICMgNiw3LDgsMTIsMTUNCnBvczVoIDwtIGMocmVwKEZBTFNFLDUpLFRSVUUsVFJVRSxUUlVFLHJlcChGQUxTRSwzKSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSwxNSkpDQoNCnRyYWluLjVpbmYgPC0gdHJhaW4uNWgmIXBvczVoDQptaDVpbmYgPC0gbG0odGFzdGUgfiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi41aW5mLF0pDQoNCm5jdlRlc3QobWg1KQ0KbmN2VGVzdChtaDVpbmYpICMgbWVqb3JhIA0KDQpzaGFwaXJvLnRlc3QocmVzaWQobWg1KSkNCnNoYXBpcm8udGVzdChyZXNpZChtaDVpbmYpKSAjIGVtcGVvcmENCg0KZHVyYmluV2F0c29uVGVzdChtaDUpDQpkdXJiaW5XYXRzb25UZXN0KG1oNWluZikgIyBhIHZlY2VzIG5vIHNlIGN1bXBsZSBsYSBoaXBvdGVzaXMgbnVsYSBkZSBubyBhdXRvY29ycmVsYWNpb24NCg0KcmVzZXR0ZXN0KG1oNSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKSANCnJlc2V0dGVzdChtaDVpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjVpbmYsXSkgIyBlbXBlb3JhDQoNCiMgRGVjaWRpbW9zIG5vIGFjdHVhbGl6YXIgZWwgbW9kZWxvIHB1ZXMgbm8gc2llbXByZSBzZSByZWNoYXphIGxhIGNvcnJlbGFjaW9uIHkgZW1wZW9yYW4gb3Ryb3MgcC12YWxvcmVzLg0KDQoNCiMgbTINCm91dGxpZXJUZXN0KG0yKQ0KaW5mbHVlbmNlUGxvdChtMikgIyAxLDEyLDE1LDE4LDI0DQpwb3MyIDwtIGMoVFJVRSxyZXAoRkFMU0UsMTApLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi4yaW5mIDwtIHRyYWluLjImIXBvczINCm0yaW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaW5mLF0pDQoNCm5jdlRlc3QobTIpDQpuY3ZUZXN0KG0yaW5mKSAjIGVtcGVvcmEgbGlnZXJhbWVudGUNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG0yKSkNCnNoYXBpcm8udGVzdChyZXNpZChtMmluZikpICMgZW1wZW9yYSBsaWdlcmFtZW50ZQ0KDQpkdXJiaW5XYXRzb25UZXN0KG0yKQ0KZHVyYmluV2F0c29uVGVzdChtMmluZikgIyBlbXBlb3JhIGJhc3RhbnRlDQoNCnJlc2V0dGVzdChtMiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMmluZixdKSANCnJlc2V0dGVzdChtMmluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMmluZixdKSAjIG1lam9yYQ0KDQojIERlY2ljaW1vcyBubyByZWRlZmluaXJsbywgeWEgcXVlIGVtcGVvcmEgZW4gbXVjaGFzIHkgbWVqb3JhIGJhc3RhbnRlIGVuIHVuYQ0KDQoNCiMgbTMNCm91dGxpZXJUZXN0KG0zKQ0KaW5mbHVlbmNlUGxvdChtMykgIyAxLDE1LDE5LDI0DQpwb3MzIDwtIGMoVFJVRSxyZXAoRkFMU0UsMTMpLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDQpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi4zaW5mIDwtIHRyYWluLjMmIXBvczMNCm0zaW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zaW5mLF0pDQoNCm5jdlRlc3QobTMpDQpuY3ZUZXN0KG0zaW5mKSAjIG1lam9yYSBwb2NvDQoNCnNoYXBpcm8udGVzdChyZXNpZChtMykpDQpzaGFwaXJvLnRlc3QocmVzaWQobTNpbmYpKSAjIG1lam9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG0zKQ0KZHVyYmluV2F0c29uVGVzdChtM2luZikgIyBlbXBlb3JhDQoNCnJlc2V0dGVzdChtMywgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uM2luZixdKSANCnJlc2V0dGVzdChtM2luZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uM2luZixdKSAjIGVtcGVvcmEgY2FzaSBsbyBwaWVyZGUNCg0KIyBEZWNpZGltb3Mgbm8gcmVkZWZpbmlybG8gcG9yIGVzdGFyIGFsIGJvcmRlIGVuIHVuIGNyaXRlcmlvIHkgbm8gbWVqb3JhciBtdWNobyBlbiBvdHJvcw0KDQoNCiMgbTQNCm91dGxpZXJUZXN0KG00KQ0KaW5mbHVlbmNlUGxvdChtNCkgIyA2LDEyLDE1LDIwLDI0DQpwb3M0IDwtIGMocmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDQpLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi40aW5mIDwtIHRyYWluLjQmIXBvczQNCm00aW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40aW5mLF0pDQoNCm5jdlRlc3QobTQpDQpuY3ZUZXN0KG00aW5mKSAjIGVtcGVvcmEgYmFzdGFudGUNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG00KSkNCnNoYXBpcm8udGVzdChyZXNpZChtNGluZikpICMgZW1wZW9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG00KQ0KZHVyYmluV2F0c29uVGVzdChtNGluZikjIGVtcGVvcmEgYmFzdGFudGUNCg0KcmVzZXR0ZXN0KG00LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pIA0KcmVzZXR0ZXN0KG00aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pICMgbWVqb3JhIGFsZ28NCg0KIyBEZWNpZGltb3Mgbm8gY2FtYmlhcmxvIHBvcnF1ZSBlbXBlb3JhIGVuIGNhc2kgdG9kbywgeSBkZSBwb3Igc2kgdGVuaWEgYnVlbm9zIHAtdmFsdWVzDQoNCg0KIyBtNQ0Kb3V0bGllclRlc3QobTUpDQppbmZsdWVuY2VQbG90KG01KSAjIDEsOCwxMiwxNSwxOCwyNA0KcG9zNSA8LSBjKFRSVUUscmVwKEZBTFNFLDYpLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi41aW5mIDwtIHRyYWluLjUmIXBvczUNCm01aW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi41aW5mLF0pDQoNCm5jdlRlc3QobTUpDQpuY3ZUZXN0KG01aW5mKSAjIGVtcGVvcmEgYmFzdGFudGUNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG01KSkNCnNoYXBpcm8udGVzdChyZXNpZChtNWluZikpICMgbWVqb3JhIA0KDQpkdXJiaW5XYXRzb25UZXN0KG01KQ0KZHVyYmluV2F0c29uVGVzdChtNWluZikgIyBubyBzZSB2ZXJpZmljYSBsYSBoaXBvdGVzaXMgbnVsYSBkZSBubyBhdXRvY29ycmVsYWNpb24NCg0KcmVzZXR0ZXN0KG01LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi41aW5mLF0pIA0KcmVzZXR0ZXN0KG01aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi41aW5mLF0pICMgZW1wZW9yYQ0KDQojIERlY2lkaW1vcyBubyBjYW1iaWFybG8gcG9yIHBlcmRlcnNlIGxhIGNvcnJlbGFjacOzbg0KDQojIE5vdGVzZSBxdWUgZW4gbG9zIG9yaWdpbmFsZXMgc2llbXByZSBzZSBjdW1wbGlhbiBsYXMgaGlwb3Rlc2lzLCBhdW5xdWUgbm8gZXJhIG5lY2VzYXJpbyBwYXJhIGVsIHByb2Nlc28NCg0KDQoNCg0KbGlzdGFfdGVzdCA8LSBsaXN0KHRlc3QuMSx0ZXN0LjIsdGVzdC4zLHRlc3QuNCx0ZXN0LjUpDQpsaXN0YV90cmFpbmggPC0gbGlzdCh0cmFpbi4xaCx0cmFpbi4yaCx0cmFpbi4zaCx0cmFpbi40aCx0cmFpbi41aCkNCmxpc3RhX3RyYWluIDwtIGxpc3QodHJhaW4uMSx0cmFpbi4yLHRyYWluLjMsdHJhaW4uNCx0cmFpbi41KQ0KDQoNCm1vZGVsb3NfaGlwIDwtIGMoIlMxIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMxIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMyIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMyIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMzIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMzIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM0IHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM0IHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM1IHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM1IHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIk5pdmVsIGRlIHNpZ25pZmljYWNpb24iKQ0KDQpoaXBfUkwgPC0gYygiRGlzdHJpYnVjacOzbl9ub3JtYWwiLA0KICAgICAgICAgICAgIk1lZGlhXzAiLA0KICAgICAgICAgICAgIlZhcmlhbnphX25vX2NvbnN0YW50ZSIsDQogICAgICAgICAgICAiTm9fQXV0b2NvcnJlbGFjacOzbiIpDQpwbGFjZWhvbGRlciA8LSB2ZWN0b3IobW9kZSA9ICJsb2dpY2FsIixsZW5ndGggPSAxMSkNCmRmX2hpcFJMIDwtIGRhdGEuZnJhbWUoIjAiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgICIxIiA9IHBsYWNlaG9sZGVyLA0KICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSBwbGFjZWhvbGRlciwNCiAgICAgICAgICAgICAgICAgICAgICAgIjMiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IG1vZGVsb3NfaGlwKQ0KDQpjb2xuYW1lcyhkZl9oaXBSTCkgPC0gaGlwX1JMDQoNCnIgPC0gMQ0KZm9yIChkdHJhaW4gaW4gbGlzdGFfdHJhaW5oKXsNCiAgbW9kZWwuSEwubG0gPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsDQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICByZXNpZHVvcyA8LSByZXNpZChtb2RlbC5ITC5sbSkNCiAgbmV3X3JvdyA8LSBjKCkNCiAgDQogIHNoYXAgPC0gcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkdW9zKSRwLnZhbHVlLDQpDQogIHQgPC0gdC50ZXN0KHJlc2lkdW9zLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUNCiAgdiA8LSByb3VuZChuY3ZUZXN0KG1vZGVsLkhMLmxtKSRwLDQpDQogIGR3IDwtIHJvdW5kKGR1cmJpbldhdHNvblRlc3QobW9kZWwuSEwubG0pJHAsNCkNCiAgDQogIG5ld19yb3cgPSBjKHNoYXAsdCx2LGR3KQ0KICBkZl9oaXBSTFtyLF0gPC0gbmV3X3Jvdw0KICByID0gciArIDINCn0NCg0KDQpyIDwtIDINCmZvciAoZHRyYWluIGluIGxpc3RhX3RyYWluKXsNCiAgbW9kZWwuTC5sbSA8LSBsbSh0YXN0ZSB+TGFjdGljLA0KICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICByZXNpZHVvcyA8LSByZXNpZChtb2RlbC5MLmxtKQ0KICBuZXdfcm93IDwtIGMoKQ0KICANCiAgc2hhcCA8LSByb3VuZChzaGFwaXJvLnRlc3QocmVzaWR1b3MpJHAudmFsdWUsNCkNCiAgdCA8LSB0LnRlc3QocmVzaWR1b3MsIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZQ0KICB2IDwtIHJvdW5kKG5jdlRlc3QobW9kZWwuTC5sbSkkcCw0KQ0KICBkdyA8LSByb3VuZChkdXJiaW5XYXRzb25UZXN0KG1vZGVsLkwubG0pJHAsNCkNCiAgDQogIG5ld19yb3cgPSBjKHNoYXAsdCx2LGR3KQ0KICBkZl9oaXBSTFtyLF0gPC0gbmV3X3Jvdw0KICByID0gciArIDINCn0NCmRmX2hpcFJMWzExLF0gPC0gYyhyZXAoMC4wNSw0KSkNCmRmX2hpcFJMICMgVG9kb3MgbG9zIG1vZGVsb3MgY3VtcGxlbiBsYXMgaGlww7N0ZXNpcw0KDQoNCg0KZXJyMSA8LSAwDQpmb3IgKGkgaW4gNSl7DQogIGR0cmFpbiA8LSBsaXN0YV90cmFpbmhbW2ldXQ0KICBkdGVzdCA8LSBsaXN0YV90ZXN0W1tpXV0NCiAgZG1vZCA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbZHRyYWluLF0pDQogIFkgPC0gY2hlZGRhcltkdGVzdCxdJHRhc3RlDQogIFloYXQgPC0gcHJlZGljdChvYmogPSBkbW9kLCBuZXdkYXRhID0gY2hlZGRhcltkdGVzdCxdKQ0KICBlcnIxIDwtIGVycjEgKyBtZWFuKChZIC0gWWhhdCleMikNCn0NCmVycjEgPC0gZXJyMS81DQplcnIxICMgSDJTICsgTEFDVElDIHRpZW5lIGVycm9yIG1lZGlvIDExLjYzDQoNCg0KZXJyMjwtMA0KZm9yIChpIGluIDUpew0KICBkdHJhaW4gPC0gbGlzdGFfdHJhaW5bW2ldXQ0KICBkdGVzdCA8LSBsaXN0YV90ZXN0W1tpXV0NCiAgZG1vZCA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbZHRyYWluLF0pDQogIFkgPC0gY2hlZGRhcltkdGVzdCxdJHRhc3RlDQogIFloYXQgPC0gcHJlZGljdChvYmogPSBkbW9kLCBuZXdkYXRhID0gY2hlZGRhcltkdGVzdCxdKQ0KICBlcnIyIDwtIGVycjIgKyBtZWFuKChZIC0gWWhhdCleMikNCn0NCg0KDQpgYGANCmBgYHtyIHJlbmRlcj1sZW1vbl9wcmludCwgZWNobz1GQUxTRX0NCmRmX2hpcFJMDQoNCg0KYGBgDQpDYWxjdWxhbW9zIGxvcyBlcnJvcmVzIGRlIGNhZGEgbcOpdG9kbyBjb21vIGxhIG1lZGlhIGRlIGxvcyBlcnJvcmVzIGRlbCBtw6l0b2RvIGFwbGljYWRvIGVuIGNhZGEgc2VlZC4gRGUgZXN0YSBtYW5lcmEsIGVsIGVycm9yIG1lZGlvIG9idGVuaWRvIGVzOg0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludCB9DQpkdDwtZGF0YS5mcmFtZSgiMSI9MCwiMiI9MCxyb3cubmFtZXM9YygiZXJyb3JlcyIpKQ0KY29sbmFtZXMoZHQpPC0gYygiTW9kZWxvIEgyUytMYWN0aWMiLCJMYWN0aWMiKQ0KZHRbMSxdPC1jKGVycjEsZXJyMikNCmR0DQpgYGANCg0KQ29tbyBlbCBlcnJvciBkZWwgbW9kZWxvIEgyUyArIExhY3RpYyBlcyBtZW5vciwgZXNlIGVzIGVsIG1vZGVsbyBxdWUgbGxhbWFyZW1vcyBmaW5hbCB5IHF1ZSBzZSBhanVzdGFyw6EgbG8gbWVqb3IgcG9zaWJsZSBhIGxvcyBkYXRvcyBkZSBudWVzdHJvIGZpY2hlcm8uDQoNCiMgQ29uY2x1c2nDs246IHByZXNlbnRhY2nDs24gZGVsIG1vZGVsbyBmaW5hbA0KDQpGaW5hbG1lbnRlIHBvciBjb21wYXJhY2nDs24gZGUgbG9zIGVycm9yZXMgc2FiZW1vcyBxdWUgZWwgbW9kZWxvIGZpbmFsIHF1ZSBwcmVzZW50YW1vcyBlczogdGFzdGUgfiBIMlMgKyBMYWN0aWMgLCBxdWUgdGllbmUgc2VudGlkbyB5YSBxdWUgQWNldGljIG5vIGVyYSBzaWduaWZpY2F0aXZhLiBvdHJvIGhlY2hvIHF1ZSBsbyByZWFmaXJtYSBlcyBxdWUgZW4gbGEgY29uc3RydWNjacOzbiBkZSBtb2RlbG9zIHNhbGllcm9uIGVuIHRvZG9zIGxvcyBjYXNvcyBlc3RlIG1vZGVsbywgc2Fsdm8gZW4gZWwgbcOpdG9kbyBiYWNrd2FyZCB5IGVuIGVsIG3DqXRvZG8gZm9yd2FyZCBkZSBsYSBwcmltZXJhIHNlbWlsbGEuDQoNCjwhLS0gYXF1aSBoYWNlcmxvIHRhYmxhIGNvbiBsbyBxdWUgbWUgaW50ZXJlc2EgLS0+DQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KbW9kZWwueSA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYyxkYXRhPWNoZWRkYXIpIA0KZGZfcmVzdW1lbiA8LSB0aWR5KG1vZGVsLnkpDQoNCmBgYA0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcmVzdW1lbg0KYGBgDQoNClByZXNlbnRhbW9zIGVsIHN1bW1hcnkgZGUgbnVlc3RybyBtb2RlbG8sIGRlbCBxdWUgc2FjYXJlbW9zIG3DoXMgaW5mb3JtY2nDs24gZW4gdW4gZnV0dXJvLg0KDQpBIHN1IHZleiBlbnNlw7FhbW9zIGxvcyBncmFmaWNvcyBkZSBlc3RlIG1vZGVsbzoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTYuNSxmaWcuYWxpZ24gPSAnY2VudGVyJ30NCnBhcihtZnJvdz1jKDIsMikpDQpwbG90KG1vZGVsLnkpDQpgYGANCg0KQWhvcmEgdmFtb3MgYSBhc2VndXJhcm5vcyBxdWUgdmVyaWZpY2EgbGFzIGhpcMOzdGVzaXMgcGFyYSB1bmEgcmVncmVzacOzbiBsaW5lYWwgeSBhZGVtw6FzIGRlIHJldmlzYXIgY29uIG91dGxpZXJUZXN0ICBxdWUgbm8gdGVuZW1vcyBvdXRsaWVycy4NClRhbWJpw6luIHBsYW50ZWFtb3MgdW5hIGhpcMOzdGVzaXMgc29icmUgbGEgbnVsaWRhZCBkZSBsYSBtZWRpYSBkZSBsb3MgZXJyb3JlcyB5IHZlbW9zIHF1ZSBzdSB2YXJpYW56YSBlcyBjb25zdGFudGUgYWRlbcOhcyBkZSBjYWxjdWxhcmxhLg0KPCEtLSBBcXVpIGRlYmVyw61hIGlyIHRhYmxhIGNvbiBwdmFsdWVzIGRlIG5vcm1hbGlkYWQuLi4uIC0tPg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMSksIjIiID0gcmVwKDAsMSksIjMiID0gcmVwKDAsMSksIjQiID0gcmVwKDAsMSksIjUiID0gcmVwKDAsMSksIjYiID0gcmVwKDAsMSksIjciID0gcmVwKDAsMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygibW9kZWwueSIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJwLU91dGxpZXJzIiwicC1Ob3JtYWxpZGFkIiwicC1NZWRpYSBudWxhIiwicC1Ib21vY2VkYXN0aWNpZGFkIiwiVmFsb3IgZGUgdmFyaWFuemEiLCJwLUF1dG9jb3JyZWxhY2nDs24iLCJwLUxpbmVhbGlkYWQiKQ0KZGZfcHZhbF9kcm9wX3AxWywxXSA8LSBvdXRsaWVyVGVzdChtb2RlbC55KSRwDQpkZl9wdmFsX2Ryb3BfcDFbLDJdIDwtIHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC55KSkkcA0KZGZfcHZhbF9kcm9wX3AxWywzXSA8LSB0LnRlc3QocmVzaWQobW9kZWwueSksbXU9MCxhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlDQpkZl9wdmFsX2Ryb3BfcDFbLDRdIDwtIG5jdlRlc3QobW9kZWwueSkkcA0KZGZfcHZhbF9kcm9wX3AxWyw1XSA8LSBzcXJ0KGRldmlhbmNlKG1vZGVsLnkpL2RmLnJlc2lkdWFsKG1vZGVsLnkpKQ0KZGZfcHZhbF9kcm9wX3AxWyw2XSA8LSBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLnkpJHANCmRmX3B2YWxfZHJvcF9wMVssN10gPC0gcmVzZXR0ZXN0KG1vZGVsLnksIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyKSRwLnZhbHVlDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQpEaWNobyBlc3RvIHByb2NlZGVtb3MgYSBsYSBwcmVzZW50YWNpw7NuIGRlbCBtb2RlbG8gY29uIHN1cyBiZXRhcyBhc29jaWFkb3MsIHF1ZSBzaSBiaWVuIHNlIHB1ZWRlbiByZWNvZ2VyIGRlbCBzdW1tYXJ5LCB0YW1iacOpbiBsb3MgY2FsY3VsYW1vcyBkZSBmb3JtYSBtYXRyaWNpYWwgaWd1YWwgcXVlIHNlIGhpem8gY29uIGVsIG1vZGVsbyBjb21wbGV0byBlbiBzdSBtb21lbnRvLg0KDQpFbCByZXN1bHRhZG8gc2Vyw61hICoqdGFzdGUgfiAtMjcuNTkxODE1ICszLjk5NDYyNjcgSDJTICsxOS44ODcyMDQgTGFjdGljKioNCk7Ds3Rlc2UgcXVlIHNpZ3VlIHNpZW5kbyBhY29yZGUgYWwgbW9kZWxvIGNvbXBsZXRvIGRvbmRlIGVsICRcYmV0YSQgZGUgTGFjdGljIGVzIG11eSBzdXBlcmlvciBlbiBjb21wYXJhY2nDs24gYWwgZGUgSDJTLg0KDQpQcmVzZW50YW1vcyBhaG9yYSAkUl57Mn0kIHkgJFJeezJ9X3thZGp9JCwgZXN0YXMgY29tbyBhbnRlcyBzZSBwdWVkZW4gcmVjb2dlciBkaXJlY3RhbWVudGUgZGVsIHN1bW1hcnksIHRhbWJpw6luIGxhcyBjYWxjdWxhbW9zIGEgcGFydGlyIGRlIGxvcyBlcnJvcmVzIHkgbGEgdGFibGEgYW5vdmEsIGRhbmRvIGVsIHJlc3VsdGFkbyBkZSAwLjY1MTcwMjQgeSAwLjYyNTkwMjUgcmVzcGVjdGl2YW1lbnRlLiBBZGVtw6FzIHByZXNlbnRhbW9zIGVsIHZlY3RvciBkZSBwLXZhbG9yZXMuDQoNCjwhLS0gQXF1aSBpcmlhIHVuIHRhYmxhIHF1ZSBwcmVzZW50ZSB0b2RvIGVsbG8gLS0+DQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQojc3VtbWFyeShtb2RlbC55KSRjb2VmZlssNF0NCg0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMSksIjIiID0gcmVwKDAsMSksIjMiID0gcmVwKDAsMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygiUC12YWxvcmVzIikpDQoNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygiSW50ZXJjZXB0IiwiSDJTIiwiTGFjdGljIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gYyhzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1sxLDRdXSxzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1syLDRdXSxzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1szLDRdXSkNCg0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCk9ic2VydmFtb3MgcXVlIHRvZG9zIGxvcyBwLXZhbG9yZXMgZXN0w6FuIHBvciBkZWJham8gZGUgbnVlc3RyYSBhbHBoYSBkZSByZWZlcmVuY2lhLg0KDQpUYW1iacOpbiBwcmVzZW50YW1vcyBpbnRlcnZhbG9zIHBhcmEgbGFzIGJldGFzIGRlIEJvbmZlcnJvbmkgeSBTY2hlZmbDqToNCjwhLS0gQXF1aSB2YSBlc28gLS0+DQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQphbHBoYSA8LSAwLjEwDQpiIDwtIHN1bW1hcnkobW9kZWwueSkkY29lZlsyOjMsIDFdDQpzLmIgPC0gc3VtbWFyeShtb2RlbC55KSRjb2VmWzI6MywgMl0NCmcgPC0gMw0KbiA8LSBucm93KGNoZWRkYXIpDQpwIDwtIG5jb2woc3VtbWFyeShtb2RlbC55KSRjb2VmKQ0KdF90ZW8gPC0gcXQoMSAtIGFscGhhIC8gKDIgKiBnKSwgbiAtIHApDQpCb21TaW1DSSA8LSBtYXRyaXgoYyhiIC0gdF90ZW8gKiBzLmIsIGIgKyB0X3RlbyAqIHMuYiksIG5jb2wgPSAyKQ0KY29uZiA8LSBjKCI1JSIsICI5NSUiKQ0KYm5hbSA8LSBjKCJIMlMiLCAiTGFjdGljIikNCmRpbW5hbWVzKEJvbVNpbUNJKSA8LSBsaXN0KGJuYW0sIGNvbmYpDQojIEJvbVNpbUNJDQpjMTwtQm9tU2ltQ0lbMSxdDQpjMjwtQm9tU2ltQ0lbMixdDQpRIDwtIHAgLSAxDQpmX3RlbyA8LSBxZigwLjksIFEsIG4gLSBwKSMwLjkgbm8gc2VyaWEgMC45NT8NClNjaFNpbUNJIDwtIG1hdHJpeChjKGIgLSBzcXJ0KFEgKiBmX3RlbykgKiBzLmIsIGIgKyBzcXJ0KFEgKiBmX3RlbykgKiBzLmIpLCBuY29sID0gMikNCmNvbmYgPC0gYygiNSUiLCAiOTUlIikNCmJuYW0gPC0gYygiSDJTIiwgIkxhY3RpYyIpDQpkaW1uYW1lcyhTY2hTaW1DSSkgPC0gbGlzdChibmFtLCBjb25mKQ0KIyBTY2hTaW1DSQ0KZDE8LVNjaFNpbUNJWzEsXQ0KZDI8LVNjaFNpbUNJWzIsXQ0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMyksIjIiID0gcmVwKDAsMyksIjMiID0gcmVwKDAsMyksIjQiID0gcmVwKDAsMyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygiSDJTIiwiTGFjdGljIiwiUG9yY2VudGFqZSIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJCb25mZXJyb25pIiwiQm9uZmVycm9uaSIsIlNjaGVmZsOpIiwiU2NoZWZmw6kiKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBjKGMxLGQxKQ0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBjKGMyLGQyKQ0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBjKCI1JSIsIjk1JSIsIjUlIiwiOTUlIikNCmRmX3B2YWxfZHJvcF9wMQ0KYGBgDQpGaW5hbG1lbnRlIGJ1c2NhbW9zIHVuYSByZXByZXNlbnRhY2nDs24gZGUgbGEgcmVncmVzacOzbiBxdWUgdGVuZW1vcyBlbiAzIGRpbWVuc2lvbmVzIHlhIHF1ZSBlbCBtb2RlbG8gZmluYWwgY29uc3RhIGRlIHVuYSB2YXJpYWJsZSByZXNwdWVzdGEgeSBkb3MgcHJlZGljdG9yYXMgeSB2ZW1vcyBlbCBwbGFubyBkZSByZWdyZXNpw7NuLCBtYXJjYW5kbyBlbiByb2pvIGxhcyBvYnNlcnZhY2lvbmVzIHF1ZSBwZW9yIHNlIGFqdXN0YW4uDQo8IS0tIEFxdWkgdmEgZXNvLCBzaSBsbyBwdWVkZSBvbmVyIG90cm8gbWVqb3IsIHBxIGEgbWkgaGF5IHVuYSBncmFmaWNhIHF1ZSBubyBzZSBtZSBlamVjdXRhIC0tPg0KDQpgYGB7ciBlY2hvID1GQUxTRX0NCnBhcihtZnJvdz1jKDEsMikpDQpwbG90X2x5KHg9SDJTLCB5PUxhY3RpYywgej10YXN0ZSwgdHlwZT0ic2NhdHRlcjNkIiwgbW9kZT0ibWFya2VycyIsIGNvbG9yPXRhc3RlKSAlPiUgDQogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0gyUyAoJSknKSwNCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnTGFjdGljICglKScpLA0KICAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICdUYXN0ZSAoMC0xMDApJykpKQ0KcGxhbmVyZWcgPC0gc2NhdHRlcnBsb3QzZCh4PUgyUywgeT1MYWN0aWMsIHo9dGFzdGUsIHBjaD0xNiwgY2V4LmxhYj0xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdobGlnaHQuM2Q9VFJVRSwgdHlwZT0iaCIsIHhsYWI9J0gyUyAoJSknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB5bGFiPSdMYWN0aWMgKCUpJywgemxhYj0nVGFzdGUgKDAtMTAwKScpDQpwbGFuZXJlZyRwbGFuZTNkKG1vZGVsLnksIGx0eS5ib3g9InNvbGlkIiwgY29sPSdtZWRpdW1ibHVlJykNCmBgYA0KDQoNCg0KIyAgQW5leG8NCg0KYGBge3IgZWNobyBUUlVFLGV2YWw9RkFMU0V9DQoNCg0KaW5zdGFsbC5wYWNrYWdlcygiZmFyYXdheSIpDQppbnN0YWxsLnBhY2thZ2VzKCJsZWFwcyIpDQppbnN0YWxsLnBhY2thZ2VzKCJNQVNTIikNCmluc3RhbGwucGFja2FnZXMoIlBBU1dSIikNCmluc3RhbGwucGFja2FnZXMoImNhciIpDQppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCmluc3RhbGwucGFja2FnZXMoIkdHYWxseSIpDQppbnN0YWxsLnBhY2thZ2VzKCJjb3JycGxvdCIpDQppbnN0YWxsLnBhY2thZ2VzKCJzY2F0dGVycGxvdDNkIikNCmluc3RhbGwucGFja2FnZXMoImxtdGVzdCIpDQppbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KaW5zdGFsbC5wYWNrYWdlcygibWl4bG0iKQ0KDQoNCmxpYnJhcnkoZmFyYXdheSkNCmxpYnJhcnkobGVhcHMpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KFBBU1dSKQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KEdHYWxseSkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoc2NhdHRlcnBsb3QzZCkNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShtaXhsbSkNCg0KDQoNCg0KDQojIDEpIEludHJvZHVjY2lvbg0KDQpkYXRhKGNoZWRkYXIpDQphdHRhY2goY2hlZGRhcikNCg0KIyBWYXJpYWJsZSBSZXNwdWVzdGE6IHRhc3RlDQojIFZhcmlhYmxlcyBQcmVkaWN0b3JhczogQWNldGljLCBIMlMsIExhY3RpYw0KDQoNCiMgRXN0dWRpYW1vcyBlbCB0aXBvIGRlIGxhcyB2YXJpYWJsZXMgcXVlIHZhbiBhIGZvcm1hciBwYXJ0ZSBkZSBsb3MgcG9zaWJsZXMgbW9kZWxvcw0Kc2FwcGx5KGNoZWRkYXIsIGNsYXNzKSAjIHRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIG51bWVyaWNhcw0KaGVhZChjaGVkZGFyKQ0KDQojIENvbXByb2JhbW9zIHF1ZSBubyBoYXkgZW50cmFkYXMgdmFjaWFzDQphbnkoaXMubmEoY2hlZGRhcikpDQoNCiMgRGUgaGFiZXJsYXMgaGFiaWRvLCBwb2RyaWFtb3MgaGFiZXIgdG9tYWRvIGxhcyBzaWd1aWVudGVzIGRlY2lzaW9uZXM6DQojICAtIGVsaW1pbmFyIGxhcyBvYnNlcnZhY2lvbmVzIGNvbiB2YWxvcmVzIE5BDQojICAtIGVsaW1pbmFyIHZhcmlhYmxlcyBzaSBtdWNoYXMgZGUgbGFzIGVudHJhZGFzIHZhY2lhcyBhcGFyZWNlbiBlbiBlbGxhICAgDQojICAtIGVtcGxlYXIgbcOpdG9kb3MgcGFyYSBwcmVkZWNpciBxdWUgdmFsb3JlcyBkZWJlcmlhbiBhcGVyY2VyIGVuIGRpY2hhcyBlbnRyYWRhcw0KDQoNCg0KIyBIaXN0b2dyYW1hcyBkZSB0b2RhcyBsYXMgdmFyaWFibGVzDQppZHMgPC0gbmFtZXMoY2hlZGRhcikNCmxheW91dChtYXRyaXgoMTo0LCBucm93ID0gMSkpDQp5X2xhYl9zdHJpbmcgPC0gIkNhbnRpZGFkIg0KZm9yIChpZCBpbiBpZHMpIHsNCiAgaGlzdChjaGVkZGFyWywgaWRdLCB4bGFiID0gaWQsIHlsYWIgPSB5X2xhYl9zdHJpbmcsIG1haW4gPSBwYXN0ZSgiSGlzdG9ncmFtIG9mICIsIGlkKSkNCiAgeV9sYWJfc3RyaW5nIDwtICIiDQp9DQoNCg0KIyBHcmFmaWNhcyBkZSBsYXMgcmVsYWNpb25lcyBlbnRyZSB2YXJpYWJsZXMuDQpwbG90KGNoZWRkYXIpDQoNCiMgR3JhZmljYXMgZGUgZGlzcGVyc2lvbiBlbnRyZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgInRhc3RlIiB5IGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMuDQpsYXlvdXQobWF0cml4KDE6MywgbnJvdyA9IDEpKQ0KDQpwbG90KEFjZXRpYywgdGFzdGUsDQogICAgIG1haW4gPSAiUmVsYWNpw7NuIGVudHJlIFRhc3RlIHkgQWNldGljIiwNCiAgICAgeGxhYiA9ICJBY2V0aWMiLCB5bGFiID0gIlRhc3RlIiwNCiAgICAgcGNoID0gMTksIGZyYW1lID0gRkFMU0UpDQoNCg0KcGxvdChIMlMsIHRhc3RlLA0KICAgICBtYWluID0gIlJlbGFjacOzbiBlbnRyZSBUYXN0ZSB5IEgyUyIsDQogICAgIHhsYWIgPSAiSDJTIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KDQoNCnBsb3QoTGFjdGljLCB0YXN0ZSwNCiAgICAgbWFpbiA9ICJSZWxhY2nDs24gZW50cmUgVGFzdGUgeSBMYWN0aWMiLA0KICAgICB4bGFiID0gIkxhY3RpYyIsIHlsYWIgPSAiVGFzdGUiLA0KICAgICBwY2ggPSAxOSwgZnJhbWUgPSBGQUxTRSkNCg0KDQpsYXlvdXQobWF0cml4KDE6MSwgbnJvdyA9IDEpKQ0Kc3VtbWFyeShjaGVkZGFyKQ0KDQoNCg0KDQoNCiMgMikgRXN0dWRpbyB5IGV2YWx1YWNpb24gZGVsIG1vZGVsbyBjb21wbGV0bw0KDQp4IDwtIG1vZGVsLm1hdHJpeCggfiBBY2V0aWMgKyBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyKQ0KYmV0YWhhdCA8LSBzb2x2ZShjcm9zc3Byb2QoeCwgeCksIGNyb3NzcHJvZCh4LCB0YXN0ZSkpDQpiZXRhaGF0IDwtIGMoYmV0YWhhdCkNCmJldGFoYXQNCg0KIyBDb21wcm9iYW1vcyBlbCByZXN1bHRhZG8gY29uIGZ1bmNpb25lcyB5YSBpbXBsZW1lbnRhZGFzDQptb2RlbC5hbGwgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhcikNCnN1bW1hcnkobW9kZWwuYWxsKQ0KbW9kZWwuYWxsJGNvZWZmaWNpZW50cw0KDQphbm92YShtb2RlbC5hbGwpDQoNCg0KDQojIEludGVydmFsb3MgZGUgY29uZmlhbnphIGRlIGxhcyBiZXRhcyBkZWwgbW9kZWxvIGNvbXBsZXRvDQpjb25maW50KG1vZGVsLmFsbCkNCg0KIyBPYnNlcnZhbW9zIHF1ZSAwIGVzdGEgZW4gZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBkZSBiZXRhXzAgeSBiZXRhX0FjZXRpYywgcGxhbnRlYW1vcyBkb3MgdGVzdHMNCiMgICAgY29uIGhpcMOzdGVzaXMgbnVsYSBiZXRhX2kgPSAwIHkgaGlwb3Rlc2lzIGFsdGVybmF0aXZhIGJldGFfaSAhPSAwLg0KDQojIENvbWVuemFtb3MgY29uIGJldGFfQWNldGljIHB1ZXMgZWwgdmFsb3IgZXN0aW1hZG8gZXMgbcOhcyBjZXJjYW5vIGEgMCBxdWUgZWwgZGUgYmV0YV8wDQptb2Rub0FjZXRpYyA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YT1jaGVkZGFyKQ0KYW5vdmEobW9kbm9BY2V0aWMsbW9kZWwuYWxsKSAjIG5vIHNvbG8gZWwgcC12YWxvciA+IDAuMDUgc2lubyBxdWUgZGUgaGVjaG8gcC12YWxvciB+IDEsIGFjZXB0YW1vcyBsYSBoaXBvdGVzaXMgbnVsYS4NCg0KbW9kbm9JbnRlcmNlcHRvciA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYyArIDAsIGRhdGE9Y2hlZGRhcikgIyBtb2RlbG8gcmVkdWNpZG8gc2luIGludGVyY2VwdG9yDQphbm92YShtb2Rub0ludGVyY2VwdG9yLG1vZGVsLmFsbCkgIyBlbCBwLXZhbG9yIGVzIG1lbm9yIHF1ZSAwLjA1LCBsdWVnbyBubyBlcyBzdWZpY2llbnRlIHBhcmEgcmVjaGF6YXIgbGEgaGlwb3Rlc2lzIG51bGENCg0KDQojIFZlYW1vcyBsb3MgcC12YWxvcmVzIGRlIGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMNCnN1bW1hcnkobW9kZWwuYWxsKSRjb2VmZlssNF0gDQojIE9ic2VydmFtc28gcXVlIGVsIHAtdmFsb3IgZGUgQWNldGljIGVzIGVsIG1hcyBlbGV2YWRvLCBlc3RlIHJlc3VsdGFkbyBqdW50byBjb24gZWwgY29udHJhdGUgZGUgaGlwb3Rlc2lzIHF1ZSBoZW1vcyBoZWNobw0KIyAgcG9kZW1vcyBkZWR1Y2lyIHF1ZSBsYSB2YXJpYWJsZSBBY2V0aWMgbm8gc2VyYSBtdXkgcmVsZXZhbnRlIHBhcmEgZWwgZXN0dWRpbyBkZSBsb3MgZGlzdGludG9zIG1vZGVsb3MgcXVlIGVzdHVkaWFyZW1vcy4NCg0KDQojIENvcnJlbGFjaW9uZXMgZGUgbGFzIHZhcmlhYmxlcyBxdWUgaW50ZXJ2aWVuZW4gZW4gZWwgbW9kZWxvIGNvbXBsZXRvDQpjb3IoY2hlZGRhcikNCmdncGFpcnMoY2hlZGRhcikNCg0KbWF0X2NvciA8LSBjb3IoY2hlZGRhciwgbWV0aG9kID0gInBlYXJzb24iKQ0KY29ycnBsb3QobWF0X2NvciwgdHlwZSA9ICJ1cHBlciIsIG9yZGVyID0gImhjbHVzdCIsIHRsLmNvbCA9ICJibGFjayIsIHRsLnNydCA9IDQ1KQ0KDQoNCiMgUG9yIHVsdGltbyB2ZWFtb3Mgc2kgaGF5IG91dGxpZXJzIGVuIGVsIG1vZGVsbyBjb21wbGV0bw0KTW9kZWwuYWxsPC1mb3J0aWZ5KG1vZGVsLmFsbCkNCm91dGxpZXJUZXN0KG1vZGVsLmFsbCkgIyBubyBsb3MgaGF5DQoNCiMgUG9yIGVsIG1ldG9kbyBkZSBCb25mZXJyb25pDQphbHBoYSA8LSAwLjA1DQpCQ1YgPC0gcXQoMS1hbHBoYS8oMiozMCksMjYpICMgZWwgdmFsb3IgY3JpdGljbyBkZSBCb25mZXJyb25pIHRfezEtYWxwaGEvMm47bi1wLTF9LCBuPTMwLHA9Mw0KQkNWDQpzdW0oYWJzKHJzdHVkZW50KG1vZGVsLmFsbCkpPkJDVikgIyBlbCBtZXRvZG8gbm8gbm9zIGRhIG5pbmd1bmEgb2JzZXJ2YWNpb24NCg0Kc29ydChhYnMocnN0YW5kYXJkKG1vZGVsLmFsbCkpLGRlY3JlYXNpbmcgPSBUUlVFKVsxOjNdICMgZXN0b3MgdmFsb3JlcyBlc3RhbiByZWxhdGl2YW1lbnRlIGxlamFub3MgZGUgQkNWDQoNCg0KIyBWZWFtb3Mgc2kgcG9yIGluZmx1ZW5jZUluZGV4UGxvdCgpIGhheSBhbGd1bmEgb2JzZXJ2YWNpb24gcXVlIHB1ZWRhIHNlciByZWxldmFudGUNCmluZmx1ZW5jZUluZGV4UGxvdChtb2RlbC5hbGwpICMgZW4gbGEgdGVyY2VyYSBncmFmaWNhIHNlIHZlIHF1ZSBsYSBvYnNlcnZhY2lvbiAxNSB0aWVuZSB1biBjb21wb3J0YW1pZW50byBhbm9ybWFsDQoNCiMgQ29tcHJvYmVtb3Mgc2kgbG9zIHN1cHVlc3RvcyBkZSBsb3MgbW9kZWxvcyBkZSByZWdyZXNpb24gbGluZWFsIG1lam9yYW4gYWwgcmV0aXJhciBlc3RhIG9ic2VydmFjaW9uDQojICBkZSBudWVzdHJvIGRhdGFzZXQuIERlIHNlciBhc2ksIGFjZXB0YW1vcyBxdWUgcHVlZGEgc2VyIHVuYSBvYnNlcnZhY2lvbiBxdWUgcGVqdWRpcXVlIGEgbnVlc3RybyBtb2RlbG8uDQptb2RlbC5hbGxfMTU8LSBsbSh0YXN0ZSB+IC4sIGRhdGEgPSBjaGVkZGFyWy0xNSxdKQ0KDQojIEhvbW9jZWRhc3RpY2lkYWQNCm5jdlRlc3QobW9kZWwuYWxsKQ0KbmN2VGVzdChtb2RlbC5hbGxfMTUpICMgZW1wZW9yYSANCg0KIyBOb3JtYWxpZGFkDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuYWxsKSkNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC5hbGxfMTUpKSMgbWVqb3JhDQoNCiMgQXV0b2NvcnJlbGFjaW9uDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLmFsbCkNCmR1cmJpbldhdHNvblRlc3QobW9kZWwuYWxsXzE1KSMgbWVqb3JhDQoNCiMgTGluZWFsaWRhZA0KcmVzZXR0ZXN0KG1vZGVsLmFsbCwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXIpIA0KcmVzZXR0ZXN0KG1vZGVsLmFsbF8xNSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXIpIyBlbXBlb3JhDQoNCiMgRW4gZWwgY29tcHV0byBnbG9iYWwgbm8gcGFyZWNlIHF1ZSBsb3MgcC12YWxvcmVzIGRlIGVzdG9zIHRlc3RzIGRlbiBhIGVudGVuZGVyIHVuYSBtZWpvcmlhIGdlbmVyYWwgZGVsIG1vZGVsby4NCiMgIFNpIGJpZW4gZXMgY2llcnRvLCB0YW1wb2NvIGxvcyBlbXBlb3JhIHkgZGVwZW5kaWVuZG8gZGVsIGNyaXRlcmlvIGEgc2VndWlyIHBvZHJpYW1vcyBkZWNpZGlyIHNpIGVzIHJlbGV2YW50ZSBvIG5vLg0KIyAgTm9zb3Ryb3MgaGVtb3MgZGVjaWRpZG8gbm8gY29uc2lkZXJhciBsYSBvYnNlcnZhY2lvbiAxNSBjb21vIHRhbC4NCg0KDQoNCg0KDQojIDMpIFNlbGVjY2lvbiBkZWwgbWVqb3IgbW9kZWxvLiBNZXRvZG9zIHBvciBwYXNvcyB5IHBvciBjcml0ZXJpb3MNCg0KIyBTZXBhcmFjaW9uIGRlbCBkYXRhc2V0IGVuIGNvbmp1bnRvcyBkZSBlbnRyZW5hbWllbnRvIHkgdGVzdCAoNzAtMzAlKQ0KDQojIEhlbW9zIGNvbnNpZGVyYWRvIHZhcmlhcyBzZW1pbGxhcyBwYXJhIGFiYXJjYXIgbcOhcyBtb2RlbG9zLiBBZGVtw6FzLCBoZW1vcyBpbnRlbnRhZG8gZXZpdGFyIA0KIyAgZW4gbGEgbWVkaWRhIGRlIGxvIHBvaWJsZSBxdWUgc2UgcmVwaXRhbiBtdWNob3MgZWxlbWVudG9zIGVuIGxvcyBkaXN0aW50b3MgY29uanVudG9zIGRlIHRlc3Qgc2VsZWNjaW9uYWRvcy4NCg0Kc2V0LnNlZWQoMSkgDQp0cmFpbi4xIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0LjEgPC0gKCF0cmFpbi4xKQ0Kc3VtKHRlc3QuMSkNCm1vZGVsLmFsbDEgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pDQoNCnNldC5zZWVkKDExMDApIA0KdHJhaW4uMiA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4yIDwtICghdHJhaW4uMikNCnN1bSh0ZXN0LjIpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC4yPT1UUlVFKSNzb2xvIDEgcHJlc2VndWltb3MNCm1vZGVsLmFsbDIgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0pDQoNCnNldC5zZWVkKDUpIA0KdHJhaW4uMyA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4zIDwtICghdHJhaW4uMykNCnN1bSh0ZXN0LjMpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC4zPT1UUlVFKQ0Kc3VtKHRlc3QuMj09VFJVRSAmIHRlc3QuMz09VFJVRSkNCm1vZGVsLmFsbDMgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0pDQoNCg0KDQojIGkpIEJBQ0tXQVJEIChhbHBoYT0wLjA1KQ0KDQpkcm9wMShtb2RlbC5hbGwxLCB0ZXN0ID0gIkYiKQ0KIyBxdWl0YW1vcyBBY2V0aWMgZGVsIG1vZGVsbyBwb3Igc2VyIGxhIGRlIG1heW9yIHAtdmFsb3INCg0KbW9kZWwudXBkYXRlQjEgPC0gdXBkYXRlKG1vZGVsLmFsbDEsIC4gfiAuIC0gQWNldGljKQ0KZHJvcDEobW9kZWwudXBkYXRlQjEsIHRlc3QgPSAiRiIpDQojIHF1aXRhbW9zIEgyUyBkZWwgbW9kZWxvIHBvciBzZXIgbGEgZGUgbWF5b3IgcC12YWxvcg0KDQptb2RlbC51cGRhdGVCMiA8LSB1cGRhdGUobW9kZWwudXBkYXRlQjEsIC4gfiAuIC0gSDJTKQ0KZHJvcDEobW9kZWwudXBkYXRlQjIsIHRlc3QgPSAiRiIpDQojIHRlcm1pbmEgZWwgcHJvY2VzbyBwdWVzIGVsIHAtdmFsb3IgZGUgTGFjdGljIG5vIGxsZWdhIGEgYWxwaGENCg0KbW9kZWwuMSA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKQ0Kc3VtbWFyeShtb2RlbC4xKQ0KDQojIFBhcmEgZXZpdGFyIHJlcGV0aXIgZXN0ZSBwcm9jZXNvIHVzYW1vcyBlbCBwYWNrYWdlIG1peGxtIGNvbiBlbCBxdWUgb2J0ZW5lbW9zIGxvcyBtaXNtb3MgcmVzdWx0YWRvcy4NCm1vZGVsLjEgPC0gbWl4bG06OmJhY2t3YXJkKG1vZGVsLmFsbDEsIGFscGhhPTAuMDUpDQpzdW1tYXJ5KG1vZGVsLjEpICMgTEFDVElDDQoNCm1vZGVsLjIgPC0gbWl4bG06OmJhY2t3YXJkKG1vZGVsLmFsbDIsIGFscGhhPTAuMDUpDQpzdW1tYXJ5KG1vZGVsLjIpICMgSDJTICsgTEFDVElDDQoNCm1vZGVsLjMgPC0gbWl4bG06OmJhY2t3YXJkKG1vZGVsLmFsbDMsIGFscGhhPTAuMDUpDQpzdW1tYXJ5KG1vZGVsLjMpICMgSDJTICsgTEFDVElDDQoNCg0KDQojIGlpKSBGT1JXQVJEIChhbHBoYT0wLjA1KQ0KU0NPUEUgPC0gKH4gLiArIEFjZXRpYyArIEgyUyArIExhY3RpYykNCm1vZGVsLmluaWNpYWwgPC0gbG0odGFzdGUgfiAxLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pICMgc29sbyBjb24gdGVybWlubyBpbmRlcGVuZGllbnRlDQoNCmFkZDEobW9kZWwuaW5pY2lhbCwgc2NvcGUgPSBTQ09QRSwgdGVzdCA9ICJGIikNCiMgQcOxYWRpbW9zIExhY3RpYyBwb3Igc2VyIGxhIHZhcmlhYmxlIHByZWRpY3RvcmEgY29uIG1lbm9yIHAtdmFsb3INCm1vZGVsLnVwZGF0ZUYxIDwtIHVwZGF0ZShtb2RlbC5pbmljaWFsLCAuIH4gLiArIExhY3RpYykNCg0KYWRkMShtb2RlbC51cGRhdGVGMSwgc2NvcGUgPSBTQ09QRSwgdGVzdCA9ICJGIikNCiMgTm8gYcOxYWRpbW9zIG5pbmd1bmEgdmFyaWFibGUgcHVlcyB0b2RvcyBsb3MgcC12YWxvcmVzIHN1cGVyYW4gbGEgYmFycmVyYSBkZSBhbHBoYQ0KDQptb2RlbC4xYSA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKQ0Kc3VtbWFyeShtb2RlbC4xYSkNCg0KDQojIEFsIGlndWFsIHF1ZSBlbiBCQUNLV0FSRCB1c2Ftb3MgZWwgcGFxdWV0ZSBtaXhsbSBwYXJhIGF1dG9tYXRpemFyIGVsIHByb2Nlc28gZGUgRk9SV0FSRC4NCm1vZGVsLjFhIDwtIG1peGxtOjpmb3J3YXJkKG1vZGVsLmFsbDEsIGFscGhhPTAuMDUpDQpzdW1tYXJ5KG1vZGVsLjFhKSAjIExBQ1RJQw0KDQptb2RlbC4yYSA8LSBtaXhsbTo6Zm9yd2FyZChtb2RlbC5hbGwyLCBhbHBoYT0wLjA1KQ0Kc3VtbWFyeShtb2RlbC4yYSkgIyBIMlMgKyBMQUNUSUMNCg0KbW9kZWwuM2EgPC0gbWl4bG06OmZvcndhcmQobW9kZWwuYWxsMywgYWxwaGE9MC4wNSkNCnN1bW1hcnkobW9kZWwuM2EpICMgSDJTICsgTEFDVElDDQoNCiMgTsOzdGVzZSBxdWUgbG9zIG1vZGVsb3Mgb2J0ZW5pZG9zIHBvciBCQUNLV0FSRCB5IEZPUldBUkQgY29pbmNpZGVuIHBhcmEgY2FkYSBjb25qdW50byB0cmFpbi4NCg0KDQoNCiMgaWlpKSBDUklURVJJT1MNCg0KIyBSMiBhanVzdGFkbw0KbW9kZWxzMSA8LSByZWdzdWJzZXRzKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKQ0KbW9kZWxzMiA8LSByZWdzdWJzZXRzKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMixdKQ0KbW9kZWxzMyA8LSByZWdzdWJzZXRzKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMyxdKQ0KDQpzdW1tYXJ5KG1vZGVsczEpDQpzdW1tYXJ5KG1vZGVsczIpDQpzdW1tYXJ5KG1vZGVsczMpDQoNCk1SMmFkajEgPC0gc3VtbWFyeShtb2RlbHMxKSRhZGpyMg0KTVIyYWRqMiA8LSBzdW1tYXJ5KG1vZGVsczIpJGFkanIyDQpNUjJhZGozIDwtIHN1bW1hcnkobW9kZWxzMykkYWRqcjINCg0Kc3VtbWFyeShtb2RlbHMxKSR3aGljaFt3aGljaC5tYXgoTVIyYWRqMSksIF0NCnN1bW1hcnkobW9kZWxzMikkd2hpY2hbd2hpY2gubWF4KE1SMmFkajIpLCBdDQpzdW1tYXJ5KG1vZGVsczMpJHdoaWNoW3doaWNoLm1heChNUjJhZGozKSwgXQ0KDQoNCg0KIyBDcCBkZSBNYWxsb3dzDQpNQ3AxIDwtIHN1bW1hcnkobW9kZWxzMSkkY3ANCk1DcDIgPC0gc3VtbWFyeShtb2RlbHMyKSRjcA0KTUNwMyA8LSBzdW1tYXJ5KG1vZGVsczMpJGNwDQoNCg0Kc3VtbWFyeShtb2RlbHMxKSR3aGljaFt3aGljaC5taW4oTUNwMSksIF0NCnN1bW1hcnkobW9kZWxzMikkd2hpY2hbd2hpY2gubWluKE1DcDIpLCBdDQpzdW1tYXJ5KG1vZGVsczMpJHdoaWNoW3doaWNoLm1pbihNQ3AzKSwgXQ0KDQoNCiMgQ3JpdGVyaW8gZGUgSW5mb3JtYWNpb24gZGUgQmF5ZXMgKEJJQykNCk1CSUMxIDwtIHN1bW1hcnkobW9kZWxzMSkkYmljDQpNQklDMiA8LSBzdW1tYXJ5KG1vZGVsczIpJGJpYw0KTUJJQzMgPC0gc3VtbWFyeShtb2RlbHMzKSRiaWMNCg0Kc3VtbWFyeShtb2RlbHMxKSR3aGljaFt3aGljaC5taW4oTUJJQzEpLCBdDQpzdW1tYXJ5KG1vZGVsczIpJHdoaWNoW3doaWNoLm1pbihNQklDMiksIF0NCnN1bW1hcnkobW9kZWxzMykkd2hpY2hbd2hpY2gubWluKE1CSUMzKSwgXQ0KDQojIENyaXRlcmlvIGRlIEluZm9ybWFjaW9uIGRlIEFrYWlrZSAoQUlDKQ0Kc3RlcEFJQyhtb2RlbC5hbGwxLCBzY29wZSA9IFNDT1BFLCBrID0gMikNCnN0ZXBBSUMobW9kZWwuYWxsMiwgc2NvcGUgPSBTQ09QRSwgayA9IDIpDQpzdGVwQUlDKG1vZGVsLmFsbDMsIHNjb3BlID0gU0NPUEUsIGsgPSAyKQ0KDQoNCiMgUGFyYSBlbCBjb25qdW50byB0cmFpbi4xIGFwYXJlY2VuIG1vZGVsb3MgY29uIExhY3RpYyB5IEgyUyArIExhY3RpYyBjb21vIHZhcmlhYmxlcyBwcmVkaWN0b3JhcywgDQojICBtaWVudHJhcyBxdWUgcGFyYSBsb3MgY29uanVudG9zIHRyYWluLjIgeSB0cmFpbi4zIHVuaWNhbWVudGUgYXBhcmVjZSBlbCBtb2RlbG8gdGFzdGUgfiBIMlMgKyBMYWN0aWMuDQptb2RlbC4xY3JpdCA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkNCg0KIyBFc3RvIG5vcyBwdWVkZSBsbGV2YXIgYSBwZW5zYXIgcXVlIGVsIG1vZGVsbyBmaW5hbCB2YXlhIGEgc2VyIGVsIHF1ZSB1dGlsaXphIEgyUyB5IExhY3RpYy4NCg0KbW9kZWwuMQ0KbW9kZWwuMWNyaXQNCm1vZGVsLjINCm1vZGVsLjMNCg0KYW5vdmEobW9kZWwuMSxtb2RlbC5hbGwxKQ0KYW5vdmEobW9kZWwuMWNyaXQsbW9kZWwuYWxsMSkNCmFub3ZhKG1vZGVsLjIsbW9kZWwuYWxsMikNCmFub3ZhKG1vZGVsLjMsbW9kZWwuYWxsMykNCiMgRGUgZXN0YSBmb3JtYSB2ZW1vcyBxdWUgbG9zIG1vZGVsb3MgY3JlYWRvcyBzb24gbWVqb3JlcyBxdWUgbG9zIGNvbXBsZXRvcy4NCg0KDQoNCg0KDQojIDQpIERpYWdub3N0aWNvLiBDb21wcm9iYWNpb25lcyBkZSBoaXBvdGVzaXMsIG91dGxpZXJzIHkgb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcw0KDQojIENvbXByb2JhY2lvbiBkZSBoaXBvdGVzaXMgZGUgbG9zICBtb2RlbG9zIA0KDQojIExpbmVhbGlkYWQNCg0KcmVzZXR0ZXN0KG1vZGVsLjEsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkgDQpyZXNldHRlc3QobW9kZWwuMWNyaXQsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkgDQpyZXNldHRlc3QobW9kZWwuMiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMixdKSANCnJlc2V0dGVzdChtb2RlbC4zLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4zLF0pIA0KIyBwLXZhbG9yZXMgPiAwLjA1IGx1ZWdvIGFjZXB0YW1vcyBoaXDDs3Rlc2lzIGRlIGxpbmVhbGlkYWQgZW4gdG9kb3MgbG9zIGNhc29zDQoNCnBsb3QoY2hlZGRhciRIMlMsIGNoZWRkYXIkdGFzdGUsDQogICAgIG1haW4gPSAiUmVsYWNpb24gZW50cmUgVGFzdGUgeSBIMlMiLA0KICAgICB4bGFiID0gIkgyUyIsIHlsYWIgPSAiVGFzdGUiLA0KICAgICBwY2ggPSAxOSwgZnJhbWUgPSBGQUxTRSkgDQpwbG90KGNoZWRkYXIkTGFjdGljLCBjaGVkZGFyJHRhc3RlLA0KICAgICBtYWluID0gIlJlbGFjaW9uIGVudHJlIFRhc3RlIHkgTGFjdGljIiwNCiAgICAgeGxhYiA9ICJMYWN0aWMiLCB5bGFiID0gIlRhc3RlIiwNCiAgICAgcGNoID0gMTksIGZyYW1lID0gRkFMU0UpIA0KDQoNCg0KIyBOb3JtYWxpZGFkIHkgQXV0b2NvcnJlbGFjaW9uDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xKSkgIyBwLXZhbG9yID4gMC4wNSBubyBzZSByZWNoYXphIGxhIGhpcMOzdGVzaXMgbnVsYSwgaS5lLiBsYSBub3JtYWxpZGFkDQpxcW5vcm0ocmVzaWQobW9kZWwuMSkpDQpxcWxpbmUocmVzaWQobW9kZWwuMSkpDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdCkpI2JpZW4NCnFxbm9ybShyZXNpZChtb2RlbC4xY3JpdCkpDQpxcWxpbmUocmVzaWQobW9kZWwuMWNyaXQpKQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMikpI2JpZW4NCnFxbm9ybShyZXNpZChtb2RlbC4yKSkNCnFxbGluZShyZXNpZChtb2RlbC4yKSkNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjMpKSNiaWVuDQpxcW5vcm0ocmVzaWQobW9kZWwuMykpDQpxcWxpbmUocmVzaWQobW9kZWwuMykpDQoNCiMgT2JzZXJ2YW1vcyBxdWUgbGFzIGNvbGFzIG5vIHNpZ3VlbiBlbCBtaXNtbyBwYXRyw7NuIHF1ZSBlbCByZXN0byBkZSBkYXRvcywgbG8gcXVlIHBvZHLDrWEgaW5kaWNhciBxdWUgDQojICBlbCBtb2RlbG8gbm8gc2lndWUgdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLiBTaW4gZW1iYXJnbywgYWwgbm8gYWZlY3RhciBhIHVuIGdyYW4gcG9yY2VudGFqZSBkZSBsb3MgZGF0b3MgeQ0KIyAgdGVuaWVuZG8gZW4gY3VlbnRhIGVsIHJlc3VsdGFkbyBwcmV2aW8gb2J0ZW5pZG8gcG9yIGVsIFRlc3QgZGUgU2hhcGlyby1XaWxrIG5vIHJlY2hhemFtb3MgbGEgaGlww7N0ZXNpcyBkZSBub3JtYWxpZGFkLg0KDQoNCiMgTWVkaWEgZGUgZXJyb3JlcyBudWxhDQoNCnQudGVzdChyZXNpZChtb2RlbC4xKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KdC50ZXN0KHJlc2lkKG1vZGVsLjFjcml0KSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KdC50ZXN0KHJlc2lkKG1vZGVsLjIpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQp0LnRlc3QocmVzaWQobW9kZWwuMyksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCiMgcC12YWxvcmVzIH4gMSA+IDAuMDUgbHVlZ28gYWNlcHRhbW9zIGxhIGhpcG90ZXNpcyBudWxhIGVuIHRvZG9zIGxvcyBjYXNvcw0KDQoNCg0KIyBBdXRvY29ycmVsYWNpb24NCg0KZHVyYmluV2F0c29uVGVzdChtb2RlbC4xKSANCmR1cmJpbldhdHNvblRlc3QobW9kZWwuMWNyaXQpIA0KZHVyYmluV2F0c29uVGVzdChtb2RlbC4yKSANCmR1cmJpbldhdHNvblRlc3QobW9kZWwuMykgDQojIHAtdmFsb3JlcyA+IDAuMDUgbHVlZ28gcmVjaGF6YW1vcyBxdWUgaGF5YSBhdXRvY29ycmVsYWNpb24NCg0KDQoNCiMgSG9tb2NlZGFzdGljaWRhZA0KDQpmbW9kZWwxIDwtIGZvcnRpZnkobW9kZWwuMSkNCmZtb2RlbDFjcml0IDwtIGZvcnRpZnkobW9kZWwuMWNyaXQpDQpmbW9kZWwyIDwtIGZvcnRpZnkobW9kZWwuMikNCmZtb2RlbDMgPC0gZm9ydGlmeShtb2RlbC4zKQ0KDQpYMSA8LSBmbW9kZWwxJC5maXR0ZWQNClkxIDwtIGZtb2RlbDEkLnN0ZHJlc2lkDQoNClgxY3JpdCA8LSBmbW9kZWwxY3JpdCQuZml0dGVkDQpZMWNyaXQgPC0gZm1vZGVsMWNyaXQkLnN0ZHJlc2lkDQoNClgyIDwtIGZtb2RlbDIkLmZpdHRlZA0KWTIgPC0gZm1vZGVsMiQuc3RkcmVzaWQNCg0KWDMgPC0gZm1vZGVsMyQuZml0dGVkDQpZMyA8LSBmbW9kZWwzJC5zdGRyZXNpZA0KDQpwbG90KFgxLCBZMSwgeWxhYiA9ICJSZXNpZHVvcyBlc3RhbmRhcml6YWRvcyIsIHhsYWIgPSAidmFsb3JlcyBhanVzdGFkb3MiKQ0KcGxvdChYMWNyaXQsIFkxY3JpdCwgeWxhYiA9ICJSZXNpZHVvcyBlc3RhbmRhcml6YWRvcyIsIHhsYWIgPSAidmFsb3JlcyBhanVzdGFkb3MiKQ0KcGxvdChYMiwgWTIsIHlsYWIgPSAiUmVzaWR1b3MgZXN0YW5kYXJpemFkb3MiLCB4bGFiID0gInZhbG9yZXMgYWp1c3RhZG9zIikjY2FzaSBjYXNpIGhheSBwYXRyb24NCnBsb3QoWDMsIFkzLCB5bGFiID0gIlJlc2lkdW9zIGVzdGFuZGFyaXphZG9zIiwgeGxhYiA9ICJ2YWxvcmVzIGFqdXN0YWRvcyIpDQojIExvcyByZXNpZHVvcyBzZSBkaXN0cmlidXllbiBkZSBmb3JtYSBob21vZ8OpbmVhIGEgbG8gbGFyZ28gZGUgdW5hIGJhbmRhIGhvcml6b250YWwsIGx1ZWdvIHNlIHZlcmlmaWNhIGxhIGhpcMOzdGVzaXMgbnVsYQ0KDQoNCm5jdlRlc3QobW9kZWwuMSkgDQpuY3ZUZXN0KG1vZGVsLjFjcml0KQ0KbmN2VGVzdChtb2RlbC4yKQ0KbmN2VGVzdChtb2RlbC4zKQ0KIyBwLXZhbG9yZXMgPiAwLjA1LCBsdWVnbyBubyBoYXkgZXZpZGVuY2lhIHBhcmEgcmVjaGF6YXIgcXVlIGxhIHZhcmlhbnphIHNlYSBjb25zdGFudGUNCg0KDQoNCiMgT3V0bGllcnMNCg0KYWxwaGEgPC0gMC4wNQ0KbjEgPC0gbnJvdyhjaGVkZGFyW3RyYWluLjEsXSkNCnAxIDwtIG5yb3coc3VtbWFyeShtb2RlbC4xKSRjb2VmKQ0KDQpuMWNyaXQgPC0gbnJvdyhjaGVkZGFyW3RyYWluLjEsXSkNCnAxY3JpdCA8LSBucm93KHN1bW1hcnkobW9kZWwuMWNyaXQpJGNvZWYpDQoNCm4yIDwtIG5yb3coY2hlZGRhclt0cmFpbi4yLF0pDQpwMiA8LSBucm93KHN1bW1hcnkobW9kZWwuMikkY29lZikNCg0KbjMgPC0gbnJvdyhjaGVkZGFyW3RyYWluLjMsXSkNCnAzIDwtIG5yb3coc3VtbWFyeShtb2RlbC4zKSRjb2VmKQ0KDQoNCiMgRWwgdmFsb3IgY3JpdGljbyBkZSBCb25mZXJyb25pIHRfezEtYWxwaGEvMm47bi1wLTF9DQpCQ1YxIDwtIHF0KDEgLSBhbHBoYSAvICgyICogbjEpLCBuMS1wMS0xKSANCkJDVjFjcml0IDwtIHF0KDEgLSBhbHBoYSAvICgyICogbjFjcml0KSwgbjFjcml0LXAxY3JpdC0xKSANCkJDVjIgPC0gcXQoMSAtIGFscGhhIC8gKDIgKiBuMiksIG4yLXAyLTEpIA0KQkNWMyA8LSBxdCgxIC0gYWxwaGEgLyAoMiAqIG4zKSwgbjMtcDMtMSkgDQoNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMSkpID4gQkNWMSkNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMWNyaXQpKSA+IEJDVjFjcml0KQ0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4yKSkgPiBCQ1YyKQ0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4zKSkgPiBCQ1YzKQ0KDQpvdXRsaWVyVGVzdChtb2RlbC4xKSNOQT8NCm91dGxpZXJUZXN0KG1vZGVsLjFjcml0KSAjTkE/DQpvdXRsaWVyVGVzdChtb2RlbC4yKSANCm91dGxpZXJUZXN0KG1vZGVsLjMpDQojIE5vIGhheSBvdXRsaWVycyBlbiBuaW5ndW5vIGRlIGxvcyBkb3MgbW9kZWxvcyBwbGFudGVhZG9zDQoNCg0KDQojIE9ic2VydmFjaW9uZXMgSW5mbHV5ZW50ZXMNCg0KIyBDcml0ZXJpbyAxOiB2YWxvcmVzIGxldmVyYWdlIChoaWkpIG1heW9yZXMgcXVlIDJwL24NCg0KWDEgPC0gbW9kZWwubWF0cml4KH4gSDJTK0xhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKQ0KWDFjcml0IDwtIG1vZGVsLm1hdHJpeCh+IEgyUytMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSkNClgyIDwtIG1vZGVsLm1hdHJpeCh+IEgyUytMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjIsXSkNClgzIDwtIG1vZGVsLm1hdHJpeCh+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMyxdKQ0KDQpIMSA8LSBYMSAlKiUgc29sdmUodChYMSkgJSolIFgxKSAlKiUgdChYMSkNCkgxY3JpdCA8LSBYMWNyaXQgJSolIHNvbHZlKHQoWDFjcml0KSAlKiUgWDFjcml0KSAlKiUgdChYMWNyaXQpDQpIMiA8LSBYMiAlKiUgc29sdmUodChYMikgJSolIFgyKSAlKiUgdChYMikNCkgzIDwtIFgzICUqJSBzb2x2ZSh0KFgzKSAlKiUgWDMpICUqJSB0KFgzKQ0KDQpoaWkxIDwtIGRpYWcoSDEpDQpoaWkxY3JpdCA8LSBkaWFnKEgxY3JpdCkNCmhpaTIgPC0gZGlhZyhIMikNCmhpaTMgPC0gZGlhZyhIMykNCg0KaENWMSA8LSAyICogcDEgLyBuMQ0KaENWMWNyaXQgPC0gMiAqIHAxY3JpdCAvIG4xY3JpdA0KaENWMiA8LSAyICogcDIgLyBuMg0KaENWMyA8LSAyICogcDMgLyBuMw0KDQpzdW0oaGlpMSA+IGhDVjEpDQp3aGljaChoaWkxPmhDVjEpIzEgIDUgMTYgMjMgMjQgMjYgDQoNCnN1bShoaWkxY3JpdCA+IGhDVjFjcml0KQ0Kd2hpY2goaGlpMWNyaXQ+aENWMWNyaXQpDQoNCnN1bShoaWkyID4gaENWMikNCndoaWNoKGhpaTI+aENWMikNCg0Kc3VtKGhpaTMgPiBoQ1YzKQ0KDQoNCiMgQ3JpdGVyaW8gMjogdmFsb3JlcyB8REZGSVRTfCBzb24gbWF5b3JlcyBxdWUgMipzcXJ0KHAvbikNCg0KZGZmaXRzQ1YxIDwtIDIgKiBzcXJ0KHAxIC8gbjEpDQpkZmZpdHNDVjFjcml0IDwtIDIgKiBzcXJ0KHAxY3JpdCAvIG4xY3JpdCkNCmRmZml0c0NWMiA8LSAyICogc3FydChwMiAvIG4yKQ0KZGZmaXRzQ1YzIDwtIDIgKiBzcXJ0KHAzIC8gbjMpDQoNCmRmZml0c21vZGVsMSA8LSBkZmZpdHMobW9kZWwuMSkNCmRmZml0c21vZGVsMWNyaXQgPC0gZGZmaXRzKG1vZGVsLjFjcml0KQ0KZGZmaXRzbW9kZWwyIDwtIGRmZml0cyhtb2RlbC4yKQ0KZGZmaXRzbW9kZWwzIDwtIGRmZml0cyhtb2RlbC4zKQ0KDQpzdW0oZGZmaXRzbW9kZWwxID4gZGZmaXRzQ1YxKQ0Kd2hpY2goZGZmaXRzbW9kZWwxID4gZGZmaXRzQ1YxKSMxIDEyIDI0IA0KDQpzdW0oZGZmaXRzbW9kZWwxY3JpdCA+IGRmZml0c0NWMWNyaXQpDQp3aGljaChkZmZpdHNtb2RlbDFjcml0ID4gZGZmaXRzQ1YxY3JpdCkjMSwgMTINCg0Kc3VtKGRmZml0c21vZGVsMiA+IGRmZml0c0NWMikNCnN1bShkZmZpdHNtb2RlbDMgPiBkZmZpdHNDVjMpDQoNCg0KDQojIENyaXRlcmlvIDM6IHZhbG9yZXMgfERGQkVUQVN8IG1heW9yZXMgcXVlIDIvc3FydChuKQ0KDQpkZmJldGFDVjEgPC0gMiAvIHNxcnQobjEpDQpkZmJldGFDVjFjcml0IDwtIDIgLyBzcXJ0KG4xY3JpdCkNCmRmYmV0YUNWMiA8LSAyIC8gc3FydChuMikNCmRmYmV0YUNWMyA8LSAyIC8gc3FydChuMykNCg0KZGZiZXRhbW9kZWwxIDwtIGRmYmV0YShtb2RlbC4xKQ0KZGZiZXRhbW9kZWwxY3JpdCA8LSBkZmJldGEobW9kZWwuMWNyaXQpDQpkZmJldGFtb2RlbDIgPC0gZGZiZXRhKG1vZGVsLjIpDQpkZmJldGFtb2RlbDMgPC0gZGZiZXRhKG1vZGVsLjMpDQoNCg0Kc3VtKGRmYmV0YW1vZGVsMVssIDFdID4gZGZiZXRhQ1YxKQ0Kc3VtKGRmYmV0YW1vZGVsMVssIDJdID4gZGZiZXRhQ1YxKQ0Kd2hpY2goZGZiZXRhbW9kZWwxWywgMV0gPiBkZmJldGFDVjEpDQp3aGljaChkZmJldGFtb2RlbDFbLCAyXSA+IGRmYmV0YUNWMSkNCg0Kc3VtKGRmYmV0YW1vZGVsMWNyaXRbLCAxXSA+IGRmYmV0YUNWMWNyaXQpDQpzdW0oZGZiZXRhbW9kZWwxY3JpdFssIDJdID4gZGZiZXRhQ1YxY3JpdCkNCnN1bShkZmJldGFtb2RlbDFjcml0WywgM10gPiBkZmJldGFDVjFjcml0KQ0Kd2hpY2goZGZiZXRhbW9kZWwxY3JpdFssIDFdID4gZGZiZXRhQ1YxY3JpdCkNCndoaWNoKGRmYmV0YW1vZGVsMWNyaXRbLCAzXSA+IGRmYmV0YUNWMWNyaXQpDQoNCnN1bShkZmJldGFtb2RlbDJbLCAxXSA+IGRmYmV0YUNWMikNCnN1bShkZmJldGFtb2RlbDJbLCAyXSA+IGRmYmV0YUNWMikNCnN1bShkZmJldGFtb2RlbDJbLCAzXSA+IGRmYmV0YUNWMikNCndoaWNoKGRmYmV0YW1vZGVsMlssIDFdID4gZGZiZXRhQ1YyKQ0Kd2hpY2goZGZiZXRhbW9kZWwyWywgM10gPiBkZmJldGFDVjIpDQoNCnN1bShkZmJldGFtb2RlbDNbLCAxXSA+IGRmYmV0YUNWMykNCnN1bShkZmJldGFtb2RlbDNbLCAyXSA+IGRmYmV0YUNWMykNCnN1bShkZmJldGFtb2RlbDNbLCAzXSA+IGRmYmV0YUNWMykNCndoaWNoKGRmYmV0YW1vZGVsM1ssIDFdID4gZGZiZXRhQ1YzKQ0Kd2hpY2goZGZiZXRhbW9kZWwzWywgM10gPiBkZmJldGFDVjMpDQoNCiMgRGFkbyBxdWUgbnVlc3RybyBkYXRzZXQgZXMgcGVxdWXDsW8sIG5vIHRlbmRyZW1zbyBlbiBjdWVudGEgZXN0ZSBtZXRvZG8gcG9yIGRhciBkZW1hc2lhZGFzIG9ic2VydmFjaW9uZXMuDQoNCg0KIyBHcmFmaWNhIGNvbiBsYXMgZGlzdGFuY2lhcyBkZSBDb29rDQppbmZsdWVuY2VQbG90KG1vZGVsLjEpDQpwb3NfaW5mbHV5ZW50ZXNfMSA8LSBjKDEsMTIsMjQpDQoNCmluZmx1ZW5jZVBsb3QobW9kZWwuMWNyaXQpDQpwb3NfaW5mbHV5ZW50ZXNfMWNyaXQgPC0gYygxLDgsMTIsMjMpDQoNCmluZmx1ZW5jZVBsb3QobW9kZWwuMikNCnBvc19pbmZsdXllbnRlc18yIDwtIGMoMSw2LDcsOCwxNSkNCg0KaW5mbHVlbmNlUGxvdChtb2RlbC4zKQ0KcG9zX2luZmx1eWVudGVzXzMgPC0gYygxLDcsMTUsMTksMjQpDQoNCg0KDQojIENvbGluZWFsaWRhZA0KdmlmKG1vZGVsLjEpICMgdGllbmUgc2VudGlkbyBwdWVzIGVuIG1vZGVsLjEgc29sbyBoYXkgdW5hIHZhcmlhYmxlIHByZWRpY3RvcmENCnZpZihtb2RlbC4xY3JpdCkNCnZpZihtb2RlbC4yKQ0KdmlmKG1vZGVsLjMpICMgY29tbyBsb3MgdmFsb3JlcyBkZSBWSUYgbm8gc29uIGdyYW5kbywgbm8gaW5kaWNhbiBjb2xpbmVhbGlkYWQgZ3JhdmUNCg0KDQojIFZhbW9zIGEgdG9tYXIgY29tbyBwb3NpYmxlcyBpbmZsdXllbnRlcyBsYXMgcXVlIGFwYXJlY2VuIHBvciB2YXJpb3MgbWV0b2RvcyBlbiBjYWRhIG1vZGVsbw0KDQojIEVuIGVsIDE6IDEgMTIgDQpwb3NfMSA8LSBjKFRSVUUscmVwKEZBTFNFLDEwKSxUUlVFLHJlcChGQUxTRSwxOCkpDQp0cmFpbi4xaW5mIDwtIHRyYWluLjEmIXBvc18xDQptb2RlbC4xaW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xaW5mLF0pDQoNCm5jdlRlc3QobW9kZWwuMSkNCm5jdlRlc3QobW9kZWwuMWluZikgIyBlbXBlb3JhIHBlcm8gc2lndWUgY3VtcGxpZW5kbyBsYSBoaXBvdGVzaXMNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjEpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjFpbmYpKSAjIG1lam9yYSBwb2NvDQoNCmR1cmJpbldhdHNvblRlc3QobW9kZWwuMSkNCmR1cmJpbldhdHNvblRlc3QobW9kZWwuMWluZikgIyBtZWpvcmENCg0KcmVzZXR0ZXN0KG1vZGVsLjEsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjFpbmYsXSkgDQpyZXNldHRlc3QobW9kZWwuMWluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMWluZixdKSAjIG1lam9yYSBiYXN0YW50ZQ0KDQojIFJlZGVmaW5pbW9zIGVsIG1vZGVsbyBlbGltaW5hbmRvIGxhcyBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIGRlIHBvc18xLg0KdHJhaW4uMWF1eDwtdHJhaW4uMQ0KdHJhaW4uMSA8LSB0cmFpbi4xaW5mDQptb2RlbC4xIDwtIG1vZGVsLjFpbmYNCg0KDQojIEVuIGVsIDFjcml0OiAxIDEyICAyMw0KcG9zXzFjcml0IDwtIGMoVFJVRSxyZXAoRkFMU0UsMTApLFRSVUUscmVwKEZBTFNFLDEwKSxUUlVFLHJlcChGQUxTRSw3KSkNCnRyYWluLjFjcml0aW5mIDwtIHRyYWluLjEmIXBvc18xY3JpdA0KbW9kZWwuMWNyaXRpbmYgPC0gbG0odGFzdGUgfkgyUytMYWN0aWMgLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xY3JpdGluZixdKQ0KDQpuY3ZUZXN0KG1vZGVsLjFjcml0KQ0KbmN2VGVzdChtb2RlbC4xY3JpdGluZikgIyBlbXBlb3JhDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdCkpDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMWNyaXRpbmYpKSAjIG1lam9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjFjcml0KQ0KZHVyYmluV2F0c29uVGVzdChtb2RlbC4xY3JpdGluZikgIyBtZWpvcmEgYmFzdGFudGUNCg0KcmVzZXR0ZXN0KG1vZGVsLjFjcml0LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pIA0KcmVzZXR0ZXN0KG1vZGVsLjFjcml0aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xY3JpdGluZixdKSAjIGVtcGVvcmEgZGVudHJvIGRlIGFjZXB0YWJsZQ0KDQojIFJlZGVmaW5pbW9zIGVsIG1vZGVsbyBlbGltaW5hbmRvIGxhcyBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIGRlIHBvc18xY3JpdC4NCnRyYWluLjFjcml0IDwtIHRyYWluLjFjcml0aW5mDQptb2RlbC4xY3JpdCA8LSBtb2RlbC4xY3JpdGluZg0KDQoNCiMgRW4gZWwgMjogNiANCnBvc18yIDwtIGMocmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDI0KSkNCnRyYWluLjJpbmYgPC0gdHJhaW4uMiYhcG9zXzINCm1vZGVsLjJpbmYgPC0gbG0odGFzdGUgfiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaW5mLF0pDQoNCm5jdlRlc3QobW9kZWwuMikNCm5jdlRlc3QobW9kZWwuMmluZikgIyBtZWpvcmEgcG9jbw0KDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMikpDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMmluZikpICMgYXByb3hpbWFkYW1lbnRlIGxvIG1pc21vDQoNCmR1cmJpbldhdHNvblRlc3QobW9kZWwuMikNCmR1cmJpbldhdHNvblRlc3QobW9kZWwuMmluZikgIyBtZWpvcmENCg0KcmVzZXR0ZXN0KG1vZGVsLjIsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjJpbmYsXSkgDQpyZXNldHRlc3QobW9kZWwuMmluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMmluZixdKSAjIGFwcm94aW1hZGFtZW50ZSBsbyBtaXNtbw0KDQojIFJlZGVmaW5pbW9zIGVsIG1vZGVsbyBlbGltaW5hbmRvIGxhcyBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIGRlIHBvc18yLg0KdHJhaW4uMiA8LSB0cmFpbi4yaW5mDQptb2RlbC4yIDwtIG1vZGVsLjJpbmYNCg0KDQojIEVuIGVsIG1vZGVsbyAzIG5vIGhhY2Vtb3MgY29tcHJvYmFjaW9uZXMgbmFkYSB5YSBxdWUgbm8gc2UgcmVwaXRlbiBvYnNlcnZhY2lvbmVzIHBvciBkaXN0aW50b3MgbWV0b2Rvcy4NCg0KDQoNCg0KDQojIDUpIEVycm9yZXMgZGUgVGVzdC4gQ29tcGFyYWNpb24gZGUgTW9kZWxvcw0KDQojIFZhbW9zIGEgY29uc2lkZXJhciBvdHJhcyBkb3Mgc2VtaWxsYXMgcGFyYSBldmFsdWFyIGxvcyBtb2RlbG9zIHkgZWxlZ2lyIGVsIG1lam9yLg0KIyBMYXMgdG9tYW1vcyBkZSBmb3JtYSBxdWUgbm8gY29pbmNpZGFuIGVuIGxhIG1lZGlkYSBkZSBsbyBwb3NpYmxlIGxvcyB0ZXN0cyBkZSBsYXMgZGlzdGludGFzIHBhcnRpY2lvbmVzLg0KIyBEaXZpZGltb3MgZWwgY29uanVudG8gdG90YWwgcGFyYSBsYXMgZG9zIHNlbWlsbGFzIG51ZXZhcy4NCg0Kc2V0LnNlZWQoKDIyMzQpKQ0KdHJhaW4uNCA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC40IDwtICghdHJhaW4uNCkNCnN1bSh0ZXN0LjQpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC40PT1UUlVFKQ0Kc3VtKHRlc3QuMj09VFJVRSAmIHRlc3QuND09VFJVRSkNCnN1bSh0ZXN0LjM9PVRSVUUgJiB0ZXN0LjQ9PVRSVUUpDQoNCg0Kc2V0LnNlZWQoKDEzMSkpDQp0cmFpbi41IDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0LjUgPC0gKCF0cmFpbi41KQ0Kc3VtKHRlc3QuNSkNCnN1bSh0ZXN0LjE9PVRSVUUgJiB0ZXN0LjU9PVRSVUUpDQpzdW0odGVzdC4yPT1UUlVFICYgdGVzdC41PT1UUlVFKQ0Kc3VtKHRlc3QuMz09VFJVRSAmIHRlc3QuNT09VFJVRSkNCnN1bSh0ZXN0LjQ9PVRSVUUgJiB0ZXN0LjU9PVRSVUUpDQoNCnRyYWluLjFoIDwtIHRyYWluLjFjcml0DQp0cmFpbi4yaCA8LSB0cmFpbi4yDQp0cmFpbi4zaCA8LSB0cmFpbi4zDQp0cmFpbi40aCA8LSB0cmFpbi40DQp0cmFpbi41aCA8LSB0cmFpbi41DQoNCiMgUmVjYWxjdWxhbW9zIHRyYWluLjIgcG9ycXVlIGZ1ZSBtb2RpZmljYWRvDQpzZXQuc2VlZCgxMTAwKQ0KdHJhaW4uMiA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KDQoNCg0KDQojIFZlYW1zbyBzaSBwb2RlbW9zIGVsaW1pbmFyIHBvc2libGVzIGluZmx1eWVudGVzIGVuIGxvcyBtb2RlbG9zIHJlc3RhbnRlcw0KDQptaDEgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjFoLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptaDIgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjJoLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptaDMgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjNoLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptaDQgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjRoLF0pDQptaDUgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjVoLF0pDQoNCm0xIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptMiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMixdKQ0KbTMgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjMsXSkNCm00IDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40LF0pDQptNSA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNSxdKQ0KDQoNCiMgQWwgaWd1YWwgcXVlIGhpY2ltb3MgZW4gNCBjb21wcm9iYW1vcyBzaSByZXRpcmFuZG8gb3V0bGllcnMgeSBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIG1lam9yYW4gbGFzIGhpcG90ZXNpcy4NCiMgIFVuaWNhbWVudGUgY29uc2lkZXJhcmVtb3Mgb2JzZXJ2YWNpb25lcyBvYnRlbmlkYXMgdGFudG8gcG9yIG91dGxpZXJUZXN0KCkgY29tbyBwb3IgaW5mbHVlbmNlUGxvdCgpLg0KDQojIG1oNA0Kb3V0bGllclRlc3QobWg0KQ0KaW5mbHVlbmNlUGxvdChtaDQpICMgNiwxMiwxNSwyNA0KcG9zNGggPC0gYyhyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsOCksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjRpbmYgPC0gdHJhaW4uNGgmIXBvczRoDQptaDRpbmYgPC0gbG0odGFzdGUgfiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40aW5mLF0pDQoNCm5jdlRlc3QobWg0KQ0KbmN2VGVzdChtaDRpbmYpICMgbWVqb3JhIE1VQ0hPDQoNCnNoYXBpcm8udGVzdChyZXNpZChtaDQpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1oNGluZikpICMgbWVqb3JhDQoNCmR1cmJpbldhdHNvblRlc3QobWg0KQ0KZHVyYmluV2F0c29uVGVzdChtaDRpbmYpICMgbWVqb3JhDQoNCnJlc2V0dGVzdChtaDQsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjRpbmYsXSkgDQpyZXNldHRlc3QobWg0aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pICMgZW1wZW9yYSBwZXJvIGVzIGFjZXB0YWJsZQ0KDQojIFJlZGVmaW5pbW9zIGVsaW1pbmFuZG8gcG9zNGggcG9yIHNlciB0YW50YSBsYSBtZWpvcmEgZW4gaG9tb2NlZGFzdGljaWRhZCBxdWUgY29tcGVuc2EgbGEgbGluZWFsaWRhZA0KdHJhaW4uNGggPC0gdHJhaW4uNGluZg0KbWg0IDwtIG1oNGluZg0KDQoNCiMgbWg1DQpvdXRsaWVyVGVzdChtaDUpDQppbmZsdWVuY2VQbG90KG1oNSkgIyA2LDcsOCwxMiwxNQ0KcG9zNWggPC0gYyhyZXAoRkFMU0UsNSksVFJVRSxUUlVFLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDE1KSkNCg0KdHJhaW4uNWluZiA8LSB0cmFpbi41aCYhcG9zNWgNCm1oNWluZiA8LSBsbSh0YXN0ZSB+IEgyUytMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjVpbmYsXSkNCg0KbmN2VGVzdChtaDUpDQpuY3ZUZXN0KG1oNWluZikgIyBtZWpvcmEgDQoNCnNoYXBpcm8udGVzdChyZXNpZChtaDUpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1oNWluZikpICMgZW1wZW9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG1oNSkNCmR1cmJpbldhdHNvblRlc3QobWg1aW5mKSAjIGEgdmVjZXMgbm8gc2UgY3VtcGxlIGxhIGhpcG90ZXNpcyBudWxhIGRlIG5vIGF1dG9jb3JyZWxhY2lvbg0KDQpyZXNldHRlc3QobWg1LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi41aW5mLF0pIA0KcmVzZXR0ZXN0KG1oNWluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKSAjIGVtcGVvcmENCg0KIyBEZWNpZGltb3Mgbm8gYWN0dWFsaXphciBlbCBtb2RlbG8gcHVlcyBubyBzaWVtcHJlIHNlIHJlY2hhemEgbGEgY29ycmVsYWNpb24geSBlbXBlb3JhbiBvdHJvcyBwLXZhbG9yZXMuDQoNCg0KIyBtMg0Kb3V0bGllclRlc3QobTIpDQppbmZsdWVuY2VQbG90KG0yKSAjIDEsMTIsMTUsMTgsMjQNCnBvczIgPC0gYyhUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjJpbmYgPC0gdHJhaW4uMiYhcG9zMg0KbTJpbmYgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjJpbmYsXSkNCg0KbmN2VGVzdChtMikNCm5jdlRlc3QobTJpbmYpICMgZW1wZW9yYSBsaWdlcmFtZW50ZQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobTIpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG0yaW5mKSkgIyBlbXBlb3JhIGxpZ2VyYW1lbnRlDQoNCmR1cmJpbldhdHNvblRlc3QobTIpDQpkdXJiaW5XYXRzb25UZXN0KG0yaW5mKSAjIGVtcGVvcmEgYmFzdGFudGUNCg0KcmVzZXR0ZXN0KG0yLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yaW5mLF0pIA0KcmVzZXR0ZXN0KG0yaW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yaW5mLF0pICMgbWVqb3JhDQoNCiMgRGVjaWNpbW9zIG5vIHJlZGVmaW5pcmxvLCB5YSBxdWUgZW1wZW9yYSBlbiBtdWNoYXMgeSBtZWpvcmEgYmFzdGFudGUgZW4gdW5hDQoNCg0KIyBtMw0Kb3V0bGllclRlc3QobTMpDQppbmZsdWVuY2VQbG90KG0zKSAjIDEsMTUsMTksMjQNCnBvczMgPC0gYyhUUlVFLHJlcChGQUxTRSwxMyksVFJVRSxyZXAoRkFMU0UsMyksVFJVRSxyZXAoRkFMU0UsNCksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjNpbmYgPC0gdHJhaW4uMyYhcG9zMw0KbTNpbmYgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjNpbmYsXSkNCg0KbmN2VGVzdChtMykNCm5jdlRlc3QobTNpbmYpICMgbWVqb3JhIHBvY28NCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG0zKSkNCnNoYXBpcm8udGVzdChyZXNpZChtM2luZikpICMgbWVqb3JhDQoNCmR1cmJpbldhdHNvblRlc3QobTMpDQpkdXJiaW5XYXRzb25UZXN0KG0zaW5mKSAjIGVtcGVvcmENCg0KcmVzZXR0ZXN0KG0zLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4zaW5mLF0pIA0KcmVzZXR0ZXN0KG0zaW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4zaW5mLF0pICMgZW1wZW9yYSBjYXNpIGxvIHBpZXJkZQ0KDQojIERlY2lkaW1vcyBubyByZWRlZmluaXJsbyBwb3IgZXN0YXIgYWwgYm9yZGUgZW4gdW4gY3JpdGVyaW8geSBubyBtZWpvcmFyIG11Y2hvIGVuIG90cm9zDQoNCg0KIyBtNA0Kb3V0bGllclRlc3QobTQpDQppbmZsdWVuY2VQbG90KG00KSAjIDYsMTIsMTUsMjAsMjQNCnBvczQgPC0gYyhyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsNCksVFJVRSxyZXAoRkFMU0UsMyksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjRpbmYgPC0gdHJhaW4uNCYhcG9zNA0KbTRpbmYgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjRpbmYsXSkNCg0KbmN2VGVzdChtNCkNCm5jdlRlc3QobTRpbmYpICMgZW1wZW9yYSBiYXN0YW50ZQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobTQpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG00aW5mKSkgIyBlbXBlb3JhDQoNCmR1cmJpbldhdHNvblRlc3QobTQpDQpkdXJiaW5XYXRzb25UZXN0KG00aW5mKSMgZW1wZW9yYSBiYXN0YW50ZQ0KDQpyZXNldHRlc3QobTQsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjRpbmYsXSkgDQpyZXNldHRlc3QobTRpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjRpbmYsXSkgIyBtZWpvcmEgYWxnbw0KDQojIERlY2lkaW1vcyBubyBjYW1iaWFybG8gcG9ycXVlIGVtcGVvcmEgZW4gY2FzaSB0b2RvLCB5IGRlIHBvciBzaSB0ZW5pYSBidWVub3MgcC12YWx1ZXMNCg0KDQojIG01DQpvdXRsaWVyVGVzdChtNSkNCmluZmx1ZW5jZVBsb3QobTUpICMgMSw4LDEyLDE1LDE4LDI0DQpwb3M1IDwtIGMoVFJVRSxyZXAoRkFMU0UsNiksVFJVRSxyZXAoRkFMU0UsMyksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjVpbmYgPC0gdHJhaW4uNSYhcG9zNQ0KbTVpbmYgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjVpbmYsXSkNCg0KbmN2VGVzdChtNSkNCm5jdlRlc3QobTVpbmYpICMgZW1wZW9yYSBiYXN0YW50ZQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobTUpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG01aW5mKSkgIyBtZWpvcmEgDQoNCmR1cmJpbldhdHNvblRlc3QobTUpDQpkdXJiaW5XYXRzb25UZXN0KG01aW5mKSAjIG5vIHNlIHZlcmlmaWNhIGxhIGhpcG90ZXNpcyBudWxhIGRlIG5vIGF1dG9jb3JyZWxhY2lvbg0KDQpyZXNldHRlc3QobTUsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjVpbmYsXSkgDQpyZXNldHRlc3QobTVpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjVpbmYsXSkgIyBlbXBlb3JhDQoNCiMgRGVjaWRpbW9zIG5vIGNhbWJpYXJsbyBwb3IgcGVyZGVyc2UgbGEgY29ycmVsYWNpw7NuDQoNCiMgTm90ZXNlIHF1ZSBlbiBsb3Mgb3JpZ2luYWxlcyBzaWVtcHJlIHNlIGN1bXBsaWFuIGxhcyBoaXBvdGVzaXMsIGF1bnF1ZSBubyBlcmEgbmVjZXNhcmlvIHBhcmEgZWwgcHJvY2Vzbw0KDQoNCg0KDQpsaXN0YV90ZXN0IDwtIGxpc3QodGVzdC4xLHRlc3QuMix0ZXN0LjMsdGVzdC40LHRlc3QuNSkNCmxpc3RhX3RyYWluaCA8LSBsaXN0KHRyYWluLjFoLHRyYWluLjJoLHRyYWluLjNoLHRyYWluLjRoLHRyYWluLjVoKQ0KbGlzdGFfdHJhaW4gPC0gbGlzdCh0cmFpbi4xLHRyYWluLjIsdHJhaW4uMyx0cmFpbi40LHRyYWluLjUpDQoNCg0KbW9kZWxvc19oaXAgPC0gYygiUzEgdGFzdGUgfiBIMnMgKyBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzEgdGFzdGUgfiBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzIgdGFzdGUgfiBIMnMgKyBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzIgdGFzdGUgfiBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzMgdGFzdGUgfiBIMnMgKyBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzMgdGFzdGUgfiBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzQgdGFzdGUgfiBIMnMgKyBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzQgdGFzdGUgfiBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzUgdGFzdGUgfiBIMnMgKyBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiUzUgdGFzdGUgfiBMYWN0aWMiLA0KICAgICAgICAgICAgICAgICAiTml2ZWwgZGUgc2lnbmlmaWNhY2lvbiIpDQoNCmhpcF9STCA8LSBjKCJEaXN0cmlidWNpw7NuX25vcm1hbCIsDQogICAgICAgICAgICAiTWVkaWFfMCIsDQogICAgICAgICAgICAiVmFyaWFuemFfbm9fY29uc3RhbnRlIiwNCiAgICAgICAgICAgICJOb19BdXRvY29ycmVsYWNpw7NuIikNCnBsYWNlaG9sZGVyIDwtIHZlY3Rvcihtb2RlID0gImxvZ2ljYWwiLGxlbmd0aCA9IDExKQ0KZGZfaGlwUkwgPC0gZGF0YS5mcmFtZSgiMCIgPSBwbGFjZWhvbGRlciwNCiAgICAgICAgICAgICAgICAgICAgICAgIjEiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgICIyIiA9IHBsYWNlaG9sZGVyLA0KICAgICAgICAgICAgICAgICAgICAgICAiMyIgPSBwbGFjZWhvbGRlciwNCiAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gbW9kZWxvc19oaXApDQoNCmNvbG5hbWVzKGRmX2hpcFJMKSA8LSBoaXBfUkwNCg0KciA8LSAxDQpmb3IgKGR0cmFpbiBpbiBsaXN0YV90cmFpbmgpew0KICBtb2RlbC5ITC5sbSA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywNCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGNoZWRkYXJbZHRyYWluLF0pDQogIHJlc2lkdW9zIDwtIHJlc2lkKG1vZGVsLkhMLmxtKQ0KICBuZXdfcm93IDwtIGMoKQ0KICANCiAgc2hhcCA8LSByb3VuZChzaGFwaXJvLnRlc3QocmVzaWR1b3MpJHAudmFsdWUsNCkNCiAgdCA8LSB0LnRlc3QocmVzaWR1b3MsIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZQ0KICB2IDwtIHJvdW5kKG5jdlRlc3QobW9kZWwuSEwubG0pJHAsNCkNCiAgZHcgPC0gcm91bmQoZHVyYmluV2F0c29uVGVzdChtb2RlbC5ITC5sbSkkcCw0KQ0KICANCiAgbmV3X3JvdyA9IGMoc2hhcCx0LHYsZHcpDQogIGRmX2hpcFJMW3IsXSA8LSBuZXdfcm93DQogIHIgPSByICsgMg0KfQ0KDQoNCnIgPC0gMg0KZm9yIChkdHJhaW4gaW4gbGlzdGFfdHJhaW4pew0KICBtb2RlbC5MLmxtIDwtIGxtKHRhc3RlIH5MYWN0aWMsDQogICAgICAgICAgICAgICAgICAgZGF0YSA9IGNoZWRkYXJbZHRyYWluLF0pDQogIHJlc2lkdW9zIDwtIHJlc2lkKG1vZGVsLkwubG0pDQogIG5ld19yb3cgPC0gYygpDQogIA0KICBzaGFwIDwtIHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZHVvcykkcC52YWx1ZSw0KQ0KICB0IDwtIHQudGVzdChyZXNpZHVvcywgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlDQogIHYgPC0gcm91bmQobmN2VGVzdChtb2RlbC5MLmxtKSRwLDQpDQogIGR3IDwtIHJvdW5kKGR1cmJpbldhdHNvblRlc3QobW9kZWwuTC5sbSkkcCw0KQ0KICANCiAgbmV3X3JvdyA9IGMoc2hhcCx0LHYsZHcpDQogIGRmX2hpcFJMW3IsXSA8LSBuZXdfcm93DQogIHIgPSByICsgMg0KfQ0KZGZfaGlwUkxbMTEsXSA8LSBjKHJlcCgwLjA1LDQpKQ0KZGZfaGlwUkwgIyBUb2RvcyBsb3MgbW9kZWxvcyBjdW1wbGVuIGxhcyBoaXDDs3Rlc2lzDQoNCg0KDQplcnIxIDwtIDANCmZvciAoaSBpbiA1KXsNCiAgZHRyYWluIDwtIGxpc3RhX3RyYWluaFtbaV1dDQogIGR0ZXN0IDwtIGxpc3RhX3Rlc3RbW2ldXQ0KICBkbW9kIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhcltkdHJhaW4sXSkNCiAgWSA8LSBjaGVkZGFyW2R0ZXN0LF0kdGFzdGUNCiAgWWhhdCA8LSBwcmVkaWN0KG9iaiA9IGRtb2QsIG5ld2RhdGEgPSBjaGVkZGFyW2R0ZXN0LF0pDQogIGVycjEgPC0gZXJyMSArIG1lYW4oKFkgLSBZaGF0KV4yKQ0KfQ0KZXJyMSA8LSBlcnIxLzUNCmVycjEgIyBIMlMgKyBMQUNUSUMgdGllbmUgZXJyb3IgbWVkaW8gMTEuNjMNCg0KDQplcnIyPC0wDQpmb3IgKGkgaW4gNSl7DQogIGR0cmFpbiA8LSBsaXN0YV90cmFpbltbaV1dDQogIGR0ZXN0IDwtIGxpc3RhX3Rlc3RbW2ldXQ0KICBkbW9kIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhcltkdHJhaW4sXSkNCiAgWSA8LSBjaGVkZGFyW2R0ZXN0LF0kdGFzdGUNCiAgWWhhdCA8LSBwcmVkaWN0KG9iaiA9IGRtb2QsIG5ld2RhdGEgPSBjaGVkZGFyW2R0ZXN0LF0pDQogIGVycjIgPC0gZXJyMiArIG1lYW4oKFkgLSBZaGF0KV4yKQ0KfQ0KZXJyMiA8LSBlcnIyLzUNCmVycjIgIyBMQUNUSUMgdGllbmUgZXJyb3IgbWVkaW8gMTkuNA0KDQplcnIxIDwgZXJyMiAjIENvbmNsdWltb3MgcXVlIGVsIG1vZGVsbyB0YXN0ZSB+IEgyUyArIExhY3RpYyBlcyBtZWpvciBxdWUgdGFzdGUgfiBMYWN0aWMuDQoNCg0KDQoNCg0KIyA2KSBDb25jbHVzaW9uDQoNCm1vZGVsLnkgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsZGF0YT1jaGVkZGFyKSAjIHRvbWFtb3MgZWwgbWVqb3IgbW9kZWxvIGRlIGxvcyBvYnRlbmlkb3MgZW4gNA0Kc3VtbWFyeShtb2RlbC55KQ0KcGxvdChtb2RlbC55KQ0KDQojIFZlYW1vcyBsb3MgcG9zaWJsZXMgb3V0bGllcnMNCm91dGxpZXJUZXN0KG1vZGVsLnkpDQppbmZsdWVuY2VQbG90KG1vZGVsLnkpDQoNCg0KIyBFc3R1ZGlvIGRlIGhpcMOzdGVzaXMgc3VwdWVzdGFzDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC55KSkgIyBub3JtYWxpZGFkIGRlIHJlc2lkdW9zDQp0LnRlc3QocmVzaWQobW9kZWwueSksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikgIyBtZWRpYSBjZXJvIGRlIGxvcyByZXNpZHVvcw0KbmN2VGVzdChtb2RlbC55KSAjIHZhcmlhbnphIGNvbnN0YW50ZSBkZSBsb3MgcmVzaWR1b3MNCmR1cmJpbldhdHNvblRlc3QobW9kZWwueSkgIyBubyBhdXRvY29ycmVsYWNpb24NCnJlc2V0dGVzdChtb2RlbC55ICxwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhcikgIyBsaW5lYWxpZGFkDQoNCiMgRWZlY3RpdmFtZW50ZSwgY3VtcGxlIHRvZGFzIGxhcyBoaXDDs3Rlc2lzDQoNCg0Kc3VtbWFyeShtb2RlbC55KSAjIGVuIGVsIHN1bW1hcnkgb2JzZXJ2YW1vcyBsb3MgdmFsb3JlcyBkZSBiZXRhaGF0LCBzdXMgcC12YWxvcmVzIHkgc2lnbWENCg0KY29lZmYgPC0gc3VtbWFyeShtb2RlbC55KSRjb2VmZlssMV0NCmNvZWZmDQoNCiMgQ2FsY3VsbyBkZSBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlIGJldGExKEgyUykgeSBiZXRhMihMYWN0aWMpDQoNCiMgTWV0b2RvIEJvbmZlcnJvbmkNCmFscGhhIDwtIDAuMTANCnN1bW1hcnkobW9kZWwueSkkY29lZg0KYiA8LSBzdW1tYXJ5KG1vZGVsLnkpJGNvZWZbMjozLCAxXQ0Kcy5iIDwtIHN1bW1hcnkobW9kZWwueSkkY29lZlsyOjMsIDJdDQpnIDwtIDMNCm4gPC0gbnJvdyhjaGVkZGFyKQ0KcCA8LSBuY29sKHN1bW1hcnkobW9kZWwueSkkY29lZikNCnRfdGVvIDwtIHF0KDEgLSBhbHBoYSAvICgyICogZyksIG4gLSBwKQ0KQm9tU2ltQ0kgPC0gbWF0cml4KGMoYiAtIHRfdGVvICogcy5iLCBiICsgdF90ZW8gKiBzLmIpLCBuY29sID0gMikNCmNvbmYgPC0gYygiNSUiLCAiOTUlIikNCmJuYW0gPC0gYygiSDJTIiwgIkxhY3RpYyIpDQpkaW1uYW1lcyhCb21TaW1DSSkgPC0gbGlzdChibmFtLCBjb25mKQ0KQm9tU2ltQ0kNCg0KIyBJbnRlcnZhbG8gZGUgY29uZmlhbnphIHNpbXVsdGFuZW8gcG9yIGVsIG1ldG9kbyBkZSBTY2hlZmZlDQpRIDwtIHAgLSAxDQpmX3RlbyA8LSBxZigwLjksIFEsIG4gLSBwKSMwLjkgbm8gc2VyaWEgMC45NT8NClNjaFNpbUNJIDwtIG1hdHJpeChjKGIgLSBzcXJ0KFEgKiBmX3RlbykgKiBzLmIsIGIgKyBzcXJ0KFEgKiBmX3RlbykgKiBzLmIpLCBuY29sID0gMikNCmNvbmYgPC0gYygiNSUiLCAiOTUlIikNCmJuYW0gPC0gYygiSDJTIiwgIkxhY3RpYyIpDQpkaW1uYW1lcyhTY2hTaW1DSSkgPC0gbGlzdChibmFtLCBjb25mKQ0KU2NoU2ltQ0kNCg0KDQojIExhIGVjdWFjacOzbiBkZSBudWVzdHJvIG1vZGVsbyBmaW5hbCBlcyB5ID0gKC0yNy42KSArIDMuOTUqeF9IICsgMTkuOSp4X0wsDQojICAgIGRvbmRlIHhfSCB5IHhfTCBkZW5vdGFuIGxvcyB2YWxvcmVzIG9ic2VydmFkb3MgZGUgSDJTIHkgTGFjdGljLg0KDQoNCnJzZSA8LSBzcXJ0KGRldmlhbmNlKG1vZGVsLnkpL2RmLnJlc2lkdWFsKG1vZGVsLnkpKQ0KcnNlICAjIHZhcmlhbnphIGRlIGxvcyByZXNpZHVvcw0KDQpwdmFsIDwtIHN1bW1hcnkobW9kZWwueSkkY29lZmZbLDRdDQpwdmFsICAjIHZlY3RvciBjb24gbG9zIHAtdmFsb3Jlcw0KDQoNCiMgQ2FsY3VsbyBkZSBzdSBSXjIgDQphbm92YShtb2RlbC55KQ0KU1NFIDwtIGFub3ZhKG1vZGVsLnkpWzMsMl0NClNTVCA8LSBhbm92YShtb2RlbC55KVsxLDJdK2Fub3ZhKG1vZGVsLnkpWzIsMl0rYW5vdmEobW9kZWwueSlbMywyXQ0KcnNxciA8LSAxIC0gU1NFL1NTVA0KcnNxcg0Kc3VtbWFyeShtb2RlbC55KSRyLnNxdWFyZWQjIGVzIGxhIG1pc21hIA0KDQojIENhbGN1bG8gZGUgc3UgUl4yIGFqdXN0YWRhDQpNU0UgPC0gU1NFL2Fub3ZhKG1vZGVsLnkpWzMsMV0NCk1TVCA8LSBTU1QvKGFub3ZhKG1vZGVsLnkpWzEsMV0rYW5vdmEobW9kZWwueSlbMiwxXSthbm92YShtb2RlbC55KVszLDFdKQ0KUmFkaiA8LTEtTVNFL01TVA0KUmFkaiAgIyBzZSBjb21wcnVlYmEgZW4gbGEgdGFibGEgc3VtbWFyeSBxdWUgZWwgdmFsb3IgZXMgY29ycmVjdG8NCg0KDQojIE9ic2VydmFtb3MgY29tbyBzZSBkaXN0cmlidXllIGxhIHZhcmlhYmxlIHRhc3RlIGVuIGZ1bmNpw7NuIGRlIEgyUyB5IExhY3RpYw0KcGxvdF9seSh4PUgyUywgeT1MYWN0aWMsIHo9dGFzdGUsIHR5cGU9InNjYXR0ZXIzZCIsIG1vZGU9Im1hcmtlciIsIGNvbG9yPXRhc3RlKSAlPiUgDQogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0gyUyAoJSknKSwNCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnTGFjdGljICglKScpLA0KICAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICdUYXN0ZSAoMC0xMDApJykpKQ0KDQoNCiMgVmVtb3MgZWwgcGxhbm8gZGUgcmVncmVzaW9uIGRlbCBtb2RlbG8gcHJvcHVlc3RvLg0KIyBFbiByb2pvIHNlIG1hcmNhbiBsYXMgb2JzZXJ2YWNpb25lcyBxdWUgcGVvciBzZSBhanVzdGFuIGFsIG1vZGVsby4NCnBsYW5lcmVnIDwtIHNjYXR0ZXJwbG90M2QoeD1IMlMsIHk9TGFjdGljLCB6PXRhc3RlLCBwY2g9MTYsIGNleC5sYWI9MSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0LjNkPVRSVUUsIHR5cGU9ImgiLCB4bGFiPSdIMlMgKCUpJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeWxhYj0nTGFjdGljICglKScsIHpsYWI9J1Rhc3RlICgwLTEwMCknKQ0KcGxhbmVyZWckcGxhbmUzZChtb2RlbC55LCBsdHkuYm94PSJzb2xpZCIsIGNvbD0nbWVkaXVtYmx1ZScpDQpgYGA=